p2824 [HEOI2016/TJOI2016]排序
分析
二分一个数表示查询位置的数是多少,将序列中大于等于这个数的数赋为1,其余赋为0,对于每一个区间查询区间和(即区间内1的个数),然后区间修改将前/后半部分修改为1,其余修改为0即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int a[100100],d[400400],col[400400],k[100100],x[100100],y[100100];
inline void update(int le,int ri,int wh,int pl,int sum){
col[wh]=-1;
if(le==ri){
d[wh]=sum;
return;
}
int mid=(le+ri)>>1;
if(mid>=pl)update(le,mid,wh<<1,pl,sum);
else update(mid+1,ri,wh<<1|1,pl,sum);
d[wh]=d[wh<<1]+d[wh<<1|1];
return;
}
inline void build(int le,int ri,int wh,int X,int Y,int sum){
if(le>=X&&ri<=Y){
col[wh]=sum;
d[wh]=(ri-le+1)*sum;
return;
}
int mid=(le+ri)>>1;
if(col[wh]!=-1){
col[wh<<1]=col[wh<<1|1]=col[wh];
d[wh<<1]=col[wh]*(mid-le+1);
d[wh<<1|1]=col[wh]*(ri-mid);
col[wh]=-1;
}
if(mid>=X)build(le,mid,wh<<1,X,Y,sum);
if(mid<Y)build(mid+1,ri,wh<<1|1,X,Y,sum);
d[wh]=d[wh<<1]+d[wh<<1|1];
return;
}
inline int q(int le,int ri,int wh,int X,int Y){
if(le>=X&&ri<=Y)return d[wh];
int mid=(le+ri)>>1,ans=0;
if(col[wh]!=-1){
col[wh<<1]=col[wh<<1|1]=col[wh];
d[wh<<1]=col[wh]*(mid-le+1);
d[wh<<1|1]=col[wh]*(ri-mid);
col[wh]=-1;
}
if(mid>=X)ans+=q(le,mid,wh<<1,X,Y);
if(mid<Y)ans+=q(mid+1,ri,wh<<1|1,X,Y);
d[wh]=d[wh<<1]+d[wh<<1|1];
return ans;
}
int main(){
int n,m,i,j,l,r,pos;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=m;i++)scanf("%d%d%d",&k[i],&x[i],&y[i]);
scanf("%d",&pos);
l=1,r=n+1;
while(r-l>1){
int mid=(l+r)>>1;
for(i=1;i<=n;i++)
update(1,n,1,i,(a[i]>=mid));
for(i=1;i<=m;i++){
int sum=q(1,n,1,x[i],y[i]);
if(k[i]){
build(1,n,1,x[i],x[i]+sum-1,1);
build(1,n,1,x[i]+sum,y[i],0);
}else {
build(1,n,1,x[i],y[i]-sum,0);
build(1,n,1,y[i]-sum+1,y[i],1);
}
}
if(q(1,n,1,pos,pos))l=mid;
else r=mid;
}
printf("%d\n",l);
return 0;
}