题解——精选推荐
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
题解
[HEOI2016/TJOI2016]排序
题⽬描述
给出⼀个 1 到 n 的排列,现在对这个排列序列进⾏ m 次局部排序,排序分为两种:
0 l r表⽰将区间 [l,r] 的数字升序排序
1 l r表⽰将区间 [l,r] 的数字降序排序
注意,这⾥是对下标在区间 [l,r] 内的数排序。
最后询问第 q 位置上的数字。
解题思路
注意询问只有⼀个,我们可以很难想到⽤⼆分答案,假设答案是mid,然后把所有⼤于等于mid的数当做1,⼩于mid的数当做0,这样我们可以吧排序问题转化成了区间变成问题,我们就可以⽤线段树来维护了,我们可以统计出线段树每个区间中1的个数,查询要排序的区间中1的个数记为cnt,如果按降序排,前cnt个数变1,剩下的变为0,最后查找要询问的数,如果是1,⼆分答案向左半边找,反之向右半边找。
#include<iostream>
#include<cstdio>
#define l(o) (o<<1)
#define r(o) (o<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int N=2e5+7;
int n,m,p;
int a[N];
struct node{
int opt,l,r;
}q[N];
int sum[N<<2],tag[N<<2];
void modify(int o,int l,int r,int val){
tag[o]=val;
sum[o]=(r-l+1)*val;
}
void up(int o){
sum[o]=sum[l(o)]+sum[r(o)];
}
void down(int o,int l,int r){
if(tag[o]!=-1){
modify(l(o),l,mid,tag[o]);
modify(r(o),mid+1,r,tag[o]);
tag[o]=-1;
}
}
void build(int o,int l,int r,int x){
tag[o]=-1;
if(l==r){
sum[o]=(a[l]>=x);
return;
}
build(l(o),l,mid,x);
build(r(o),mid+1,r,x);
up(o);
}
void change(int o,int l,int r,int L,int R,int val){
if(L<=l&&R>=r){
modify(o,l,r,val);
return;
}
down(o,l,r);
if(L<=mid)change(l(o),l,mid,L,R,val);
if(R>mid)change(r(o),mid+1,r,L,R,val);
up(o);
}
int ask(int o,int l,int r,int L,int R){
if(L<=l&&R>=r){
return sum[o];
}
down(o,l,r);
int res=0;
if(L<=mid)res+=ask(l(o),l,mid,L,R);
if(R>mid)res+=ask(r(o),mid+1,r,L,R);
return res;
}
int judge(int x){
build(1,1,n,x);
int cnt;
for(int i=1;i<=m;i++){
cnt=ask(1,1,n,q[i].l,q[i].r);
if(q[i].opt==1){
if(cnt!=0)change(1,1,n,q[i].l,q[i].l+cnt-1,1); change(1,1,n,q[i].l+cnt,q[i].r,0);
}else{
change(1,1,n,q[i].l,q[i].r-cnt,0);
if(cnt!=0)change(1,1,n,q[i].r-cnt+1,q[i].r,1); }
}
return ask(1,1,n,p,p);
// return 0;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&q[i].opt,&q[i].l,&q[i].r); }
scanf("%d",&p);
int l1=1,r1=n;
int ans;
while(l1<=r1){
int mid1=(l1+r1)>>1;
if(judge(mid1)){
ans=mid1;
l1=mid1+1;
}else r1=mid1-1;
}
cout<<ans;
}Processing math: 100%。