bzoj4552[Tjoi2016&Heoi2016]排序
题意:
给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序,最后询问第q位置上的数字。
题解:
二分最后这个数,判定一个数就是令数组中>它为1,≤它的为0。然后把排序转成线段树区间赋值,最后查询q位置的数。如果为1则用来判定的数<答案,如果为0则用来判定的数≥答案。反思:查询区间里有多少个1后,区间赋值时如果查询结果为0,那么区间赋值左端点=r-0+1,右端点=r,则会导致左端点大于右端点,那么就会wa,当查询结果等于区间长度时也会发生类似情况。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 100010 5 #define inc(i,j,k) for(int i=j;i<=k;i++) 6 using namespace std; 7 8 inline int read(){ 9 char ch=getchar(); int f=1,x=0; 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 11 return f*x; 12 } 13 int n,m,v[maxn],opt[maxn],x[maxn],y[maxn],l,r,k,sm[maxn*5],tag[maxn*5],ll[maxn*5],rr[maxn*5]; bool bit[maxn]; 14 void update(int x){sm[x]=sm[x<<1]+sm[x<<1|1];} 15 void pushdown(int x){ 16 if(tag[x]!=-1&&ll[x]!=rr[x]){ 17 sm[x<<1]=tag[x]*(rr[x<<1]-ll[x<<1]+1); tag[x<<1]=tag[x]; 18 sm[x<<1|1]=tag[x]*(rr[x<<1|1]-ll[x<<1|1]+1); tag[x<<1|1]=tag[x]; 19 tag[x]=-1; 20 } 21 } 22 void build(int x,int l,int r){ 23 tag[x]=-1; ll[x]=l; rr[x]=r; if(l==r){sm[x]=bit[l]; return;} int mid=(l+r)>>1; 24 build(x<<1,l,mid); build(x<<1|1,mid+1,r); update(x); 25 } 26 void modify(int x,int ql,int qr,bool bit){ 27 if(ql>qr)return; pushdown(x); 28 if(ql<=ll[x]&&rr[x]<=qr){tag[x]=bit; sm[x]=bit*(rr[x]-ll[x]+1); return;} int mid=(ll[x]+rr[x])>>1; 29 if(ql<=mid)modify(x<<1,ql,qr,bit); if(mid<qr)modify(x<<1|1,ql,qr,bit); update(x); 30 } 31 int query(int x,int ql,int qr){ 32 pushdown(x); 33 if(ql<=ll[x]&&rr[x]<=qr){return sm[x];} int mid=(ll[x]+rr[x])>>1,q=0; 34 if(ql<=mid)q+=query(x<<1,ql,qr); if(mid<qr)q+=query(x<<1|1,ql,qr); return q; 35 } 36 bool check(int o){ 37 inc(i,1,n)bit[i]=(v[i]>o); build(1,1,n); 38 inc(i,1,m){ 39 int q=query(1,x[i],y[i]); 40 if(!opt[i])modify(1,x[i],y[i]-q,0),modify(1,y[i]-q+1,y[i],1); 41 else modify(1,x[i],x[i]+q-1,1),modify(1,x[i]+q,y[i],0); 42 } 43 if(query(1,k,k))return 1;else return 0; 44 } 45 int main(){ 46 n=read(); m=read(); inc(i,1,n)v[i]=read(); inc(i,1,m)opt[i]=read(),x[i]=read(),y[i]=read(); 47 k=read(); l=1; r=n; 48 while(l<r){ 49 int mid=(l+r)>>1; if(check(mid))l=mid+1;else r=mid; 50 } 51 printf("%d",l); 52 }
20160630