[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 }

 

posted @ 2018-03-08 10:27  skylee03  阅读(134)  评论(0编辑  收藏  举报