[TJOI2016][HEOI2016]排序
题目大意:
给定一个$1\sim n(n\leq10^5)$的全排列,有$m(m\leq10^5)$次操作,每次把区间$[l,r]$按照升序或降序排序。最后询问所有操作完成后,位置为$q$的数是多少。
思路:
题目只需要求位置为$q$的数是多少,而并不关心其他的数是多少。因此排序时也只需要考虑答案的那个数。二分答案$k$,将$<k$的数当成0,$\geq k$的数当成1,原序列就变成了一个01序列。这样排序时只需要统计区间内0和1的个数,线段树区间修改即可。若排序后$q$上的值为1,则答案$\geq k$,否则$<k$。
1 #include<cstdio> 2 #include<cctype> 3 #include<algorithm> 4 inline int getint() { 5 register char ch; 6 while(!isdigit(ch=getchar())); 7 register int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 const int N=100001,M=100000; 12 int n,m,q,a[N]; 13 struct Modify { 14 bool type; 15 int l,r; 16 }; 17 Modify o[M]; 18 class SegmentTree { 19 #define _left <<1 20 #define _right <<1|1 21 private: 22 int val[N<<2],tag[N<<2]; 23 void push_up(const int &p) { 24 val[p]=val[p _left]+val[p _right]; 25 } 26 void push_down(const int &p,const int &b,const int &e) { 27 if(tag[p]==-1) return; 28 const int mid=(b+e)>>1; 29 tag[p _left]=tag[p _right]=tag[p]; 30 val[p _left]=tag[p]*length(b,mid); 31 val[p _right]=tag[p]*length(mid+1,e); 32 tag[p]=-1; 33 } 34 int length(const int &b,const int &e) const { 35 return e-b+1; 36 } 37 public: 38 void build(const int &p,const int &b,const int &e,const int &k) { 39 if(b==e) { 40 val[p]=a[b]>=k; 41 return; 42 } 43 tag[p]=-1; 44 const int mid=(b+e)>>1; 45 build(p _left,b,mid,k); 46 build(p _right,mid+1,e,k); 47 push_up(p); 48 } 49 void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const bool &x) { 50 if(b==l&&e==r) { 51 tag[p]=x; 52 val[p]=x*length(b,e); 53 return; 54 } 55 push_down(p,b,e); 56 const int mid=(b+e)>>1; 57 if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x); 58 if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x); 59 push_up(p); 60 } 61 int query(const int &p,const int &b,const int &e,const int &l,const int &r) { 62 if(b==l&&e==r) return val[p]; 63 push_down(p,b,e); 64 const int mid=(b+e)>>1; 65 int ret=0; 66 if(l<=mid) ret+=query(p _left,b,mid,l,std::min(mid,r)); 67 if(r>mid) ret+=query(p _right,mid+1,e,std::max(mid+1,l),r); 68 return ret; 69 } 70 #undef _left 71 #undef _right 72 }; 73 SegmentTree t; 74 inline bool check(const int &k) { 75 t.build(1,1,n,k); 76 for(register int i=0;i<m;i++) { 77 const int opt=o[i].type,l=o[i].l,r=o[i].r,cnt1=t.query(1,1,n,l,r),cnt0=r-l+1-cnt1; 78 if(opt==0) { 79 if(cnt0) t.modify(1,1,n,l,l+cnt0-1,0); 80 t.modify(1,1,n,l+cnt0,r,1); 81 } 82 if(opt==1) { 83 if(cnt1) t.modify(1,1,n,l,l+cnt1-1,1); 84 t.modify(1,1,n,l+cnt1,r,0); 85 } 86 } 87 return t.query(1,1,n,q,q); 88 } 89 int main() { 90 n=getint(),m=getint(); 91 for(register int i=1;i<=n;i++) a[i]=getint(); 92 for(register int i=0;i<m;i++) { 93 const int opt=getint(),l=getint(),r=getint(); 94 o[i]=(Modify){opt,l,r}; 95 } 96 q=getint(); 97 int l=1,r=n; 98 while(l<=r) { 99 const int mid=(l+r)>>1; 100 if(check(mid)) { 101 l=mid+1; 102 } else { 103 r=mid-1; 104 } 105 } 106 printf("%d\n",l-1); 107 return 0; 108 }