【题意概述】
对一个1到n的排列做m次区间排序,最后询问位置q上面的数。
【题解】
区间排序的效率是nlogn,所以暴力做的话效率是mnlogn,显然达不到要求。
我们考虑二分答案。如果某个位置的数比mid小,就设为0,如果么某个位置的数大于等于mid,就设为1. check的时候我们只需对01序列排序就好了,这个可以用线段树做到logn.
如果排序后位置q的数为1,那么就表示原来这里的数大于等于mid,所以我们要挪动l,否则挪动r.
总的时间复杂度为m*logn*logn
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 #define rg register 6 #define N 30010 7 #define ls (u<<1) 8 #define rs (u<<1|1) 9 #define len(x) (a[x].r-a[x].l+1) 10 using namespace std; 11 int n,m,v[N],l,r,mid,pos; 12 struct tree{ 13 int l,r,c0,c1,num; bool same; 14 }a[N<<2]; 15 struct opt{ 16 int l,r,type; 17 }b[N]; 18 inline int read(){ 19 int k=0,f=1; char c=getchar(); 20 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 21 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 22 return k*f; 23 } 24 void build(int u,int l,int r){ 25 a[u].l=l; a[u].r=r; a[u].same=0; a[u].c0=a[u].c1=0; 26 if(l<r){ 27 int mid=(l+r)>>1; 28 build(ls,l,mid); build(rs,mid+1,r); 29 a[u].c0=a[ls].c0+a[rs].c0; a[u].c1=a[ls].c1+a[rs].c1; 30 } 31 else{ 32 if(v[l]>=mid) a[u].c1=1,a[u].c0=0; 33 else a[u].c0=1,a[u].c1=0; 34 } 35 } 36 inline void pushdown(int u){ 37 a[u].same=0; a[ls].same=a[rs].same=1; 38 a[ls].num=a[rs].num=a[u].num; 39 if(!a[u].num) a[ls].c0=len(ls),a[ls].c1=0,a[rs].c0=len(rs),a[rs].c1=0; 40 else a[ls].c0=0,a[ls].c1=len(ls),a[rs].c0=0,a[rs].c1=len(rs); 41 } 42 void update(int u,int l,int r,int num){ 43 if(l<=a[u].l&&a[u].r<=r){ 44 a[u].same=1; a[u].num=num; 45 if(num==1) a[u].c1=len(u),a[u].c0=0; 46 else a[u].c0=len(u),a[u].c1=0; 47 return; 48 } 49 if(a[u].same) pushdown(u); 50 int mid=(a[u].l+a[u].r)>>1; 51 if(l<=mid) update(ls,l,r,num); 52 if(r>mid) update(rs,l,r,num); 53 a[u].c0=a[ls].c0+a[rs].c0; 54 a[u].c1=a[ls].c1+a[rs].c1; 55 } 56 int query0(int u,int l,int r){ 57 if(l<=a[u].l&&a[u].r<=r) return a[u].c0; 58 if(a[u].same) pushdown(u); 59 int mid=(a[u].l+a[u].r)>>1,ret=0; 60 if(l<=mid) ret=query0(ls,l,r); 61 if(r>mid) ret+=query0(rs,l,r); 62 return ret; 63 } 64 int query1(int u,int l,int r){ 65 if(l<=a[u].l&&a[u].r<=r) return a[u].c1; 66 if(a[u].same) pushdown(u); 67 int mid=(a[u].l+a[u].r)>>1,ret=0; 68 if(l<=mid) ret=query1(ls,l,r); 69 if(r>mid) ret+=query1(rs,l,r); 70 return ret; 71 } 72 inline bool check(){ 73 build(1,1,n); int r0=0,r1=0; 74 for(rg int i=1;i<=m;i++){ 75 r0=query0(1,b[i].l,b[i].r); r1=query1(1,b[i].l,b[i].r); 76 if(b[i].type==0) update(1,b[i].l,b[i].l+r0-1,0),update(1,b[i].l+r0,b[i].r,1); 77 else update(1,b[i].l,b[i].l+r1-1,1),update(1,b[i].l+r1,b[i].r,0); 78 } 79 r0=query0(1,pos,pos); r1=query1(1,pos,pos); 80 return r1>0; 81 } 82 int main(){ 83 n=read(); m=read(); 84 for(rg int i=1;i<=n;i++) v[i]=read(); 85 for(rg int i=1;i<=m;i++) b[i].type=read(),b[i].l=read(),b[i].r=read(); 86 pos=read(); 87 l=1,r=n+1; 88 while(l+1<r){ 89 mid=(l+r)>>1; 90 if(check()) l=mid; else r=mid; 91 } 92 printf("%d ",l); 93 }