[HEOI2016/TJOI2016]排序 解题报告
Posted brucew-07
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HEOI2016/TJOI2016]排序 解题报告相关的知识,希望对你有一定的参考价值。
题意
给出一个大小为 (n) 的排列, 对这个排列进行 (m) 次操作, 操作分为以下两种,
0 l r
表示将区间 ([l,r]) 的数升序排序.1 l r
表示将区间 ([l,r]) 的数降序排序.
询问 (m) 次操作后下标为 (q) 的数字.
思路
不看题解打死也想不出来系列
考虑二分答案.
设当前二分的答案为 (mid), 把原排列中 大于等于 (mid) 的数标记为 (1), 小于 (mid) 的数标记为 (0).
对于这样的一个 (0,1) 串, 我们可以用线段树实现 (log n) 的排序.
若当前区间 (l,r) 的区间和为 (num), 那么就代表有 (num) 个 (1) 和 (r-l+1-num) 个 (0), 然后我们只需按要求把区间的前部分设为 (0) 或 (1), 后部分设为另一个数就行了.
最后判断一下下标为 (q) 的数字是否为 (1), 若是, 则另 (l=mid+1), 否则另 (r=mid-1).
代码
#include<bits/stdc++.h>
using namespace std;
const int _=1e5+7;
const int __=4e5+7;
int n,m,q,a[_],sum[__],tag[__],ans,x;
struct oper{
int l,r,ty;
}op[_];
void init(){
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&op[i].ty,&op[i].l,&op[i].r);
cin>>q;
}
void build(int k,int l,int r){
tag[k]=-1;
if(l==r){ sum[k]= a[l]>=x; return; }
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
sum[k]=sum[k<<1]+sum[k<<1|1];
}
void upd(int k,int l,int r,bool w){
sum[k]= w ?r-l+1 :0;
tag[k]=w;
}
void psd(int k,int l,int r){
if(tag[k]==-1) return;
int mid=(l+r)>>1;
upd(k<<1,l,mid,tag[k]);
upd(k<<1|1,mid+1,r,tag[k]);
tag[k]=-1;
}
void modify(int k,int l,int r,int x,int y,bool w){
if(x>y) return;
if(l>=x&&r<=y){ upd(k,l,r,w); return; }
psd(k,l,r);
int mid=(l+r)>>1;
if(x<=mid) modify(k<<1,l,mid,x,y,w);
if(y>mid) modify(k<<1|1,mid+1,r,x,y,w);
sum[k]=sum[k<<1]+sum[k<<1|1];
}
int query(int k,int l,int r,int x,int y){
if(l>=x&&r<=y) return sum[k];
psd(k,l,r);
int mid=(l+r)>>1,res=0;
if(x<=mid) res+=query(k<<1,l,mid,x,y);
if(y>mid) res+=query(k<<1|1,mid+1,r,x,y);
return res;
}
bool judge(int mid){
x=mid;
build(1,1,n);
for(int i=1;i<=m;i++){
int num=query(1,1,n,op[i].l,op[i].r);
if(!op[i].ty){
modify(1,1,n,op[i].l,op[i].r-num,0);
modify(1,1,n,op[i].r-num+1,op[i].r,1);
}
else{
modify(1,1,n,op[i].l,op[i].l+num-1,1);
modify(1,1,n,op[i].l+num,op[i].r,0);
}
}
return query(1,1,n,q,q);
}
void run(){
int l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
if(judge(mid)){ ans=mid; l=mid+1; }
else r=mid-1;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("x.in","r",stdin);
freopen("x.out","w",stdout);
#endif
init();
run();
printf("%d
",ans);
}
以上是关于[HEOI2016/TJOI2016]排序 解题报告的主要内容,如果未能解决你的问题,请参考以下文章