• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

yongchaoD

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

[ABC352D] Permutation Subsequence(线段树,维护区间最大小值)

题目来源:https://www.luogu.com.cn/problem/AT_abc352_d
//
题意:“这sb题,题意看了很久很久~,才看懂,不要欺负我语文撇行不行”。 给你1~n的无序排列,从n个数中找出k个数字,要求这k个数字有序排列后都是连续的,找到k个数字中在原来排列的下标极差,求出所有组合的最小极差。
//样例:
n=10,k=5
10 1 6 8 7 2 5 9 3 4
其中一种组合是连续数字的5到9,最大的下标是8(数字9),最小的下标是3(数字6),极差就是5。
//
思路:对n个数字进行排序后得到:
数字:1 2 3 4 5 6 7 8 9 10
下标:2 6 9 10 7 3 5 4 8 1
这n个数字连续取k个,都是符合条件的(题目中的下标递增,nm的怎么取,只要是连续的k个数字,肯定都是下标递增的啊),然后坐标极差就是k个数字中最大下标减去最小下标。
直接把这n个排好序的数字的下标仍在线段树里面,然会枚举1到n-k+1,找到{i,i+1,i+2...i+k-1}里面的两个最值,得出极差,然后枚举取最小的就得出答案了。

//题解:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+9;
int n,k;
pair<int,int>arr[N];
vector<pair<int,int>>tree(4*N,pair<int,int>(0,0));//first维护最大值,second维护最小值

int lp(int p) {return p<<1;}
int rp(int p) {return p<<1 |1;}

void pushup(int p){
    tree[p].first=max(tree[lp(p)].first,tree[rp(p)].first);
    tree[p].second=min(tree[lp(p)].second,tree[rp(p)].second);
}

void build(int s,int t,int p){
    if(s==t){
        tree[p].first=arr[s].second;
        tree[p].second=arr[s].second;
        return;
    }
     int m=(s+t)>>1;
     build(s,m,lp(p)),build(m+1,t,rp(p));
      pushup(p);
}

int query_Min(int l,int r,int s,int t,int p){
    if(l<=s && r>=t){
        return tree[p].second;
    }
     int m=(s+t)>>1,Min1=N,Min2=N;
     if(l<=m) { Min1=query_Min(l,r,s,m,lp(p));}
     if(r>=m+1) {Min2=query_Min(l,r,m+1,t,rp(p));}
      return min(Min1,Min2);
}

int query_Max(int l,int r,int s,int t,int p){
    if(l<=s && r>=t){
        return tree[p].first;
    }
    int m=(s+t)>>1,Max1=-N,Max2=-N;
    if(l<=m) { Max1=query_Max(l,r,s,m,lp(p));}
    if(r>=m+1) {Max2=query_Max(l,r,m+1,t,rp(p));}
    return max(Max1,Max2);
}

int main()
{
     cin>>n>>k;
     for(int i=1;i<=n;i++){
         cin>>arr[i].first;
          arr[i].second=i;
     }
      sort(arr+1,arr+1+n);

       build(1,n,1);//tree[]来维护arr.second的最值
       int t1,t2,Min=N;
        for(int i=1;i<=n-k+1;i++){
//            cout<<query(i,i+k-1,1,n,1)<<'\n';
           t1=query_Max(i,i+k-1,1,n,1);
           t2=query_Min(i,i+k-1,1,n,1);
           Min=min(Min,t1-t2);
        }
          cout<<Min<<'\n';
    return 0;
}

posted on 2024-07-18 15:01  yongchaoD  阅读(24)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3