洛谷P2824 [HEOI2016/TJOI2016]排序——题解

P2824 [HEOI2016/TJOI2016]排序

在在线算法的角度思考,发现序列排序的复杂度如何也难以简化(否则想出来的简化办法就进教科书了),故尝试从离线算法的角度思考。

尝试思考二分。二分在大部分情况下都能将模型大程度简化(或说二分多提供了一个限制性条件,将各种奇怪的问题简化为判定性问题,毕竟“能不能”和“怎么才能”这两种问题的难度大部分情况下是完全不同的吧),对于二分的答案mid,按与mid的大于等于/小于的关系将序列转化为01数列,发现给一段01序列排序只需log n的时间复杂度。故有做法:

 

 

注意一段区间的1的个数cnt可能为0,这时对于线段树的修改操作的区间会发生区间左端点大于右端点的诡异情形,故需特判,否则RE。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 
  5 #define dmid ((l+r)>>1)
  6 
  7 using namespace std;
  8 
  9 const int N=1e5+5;
 10 
 11 int n,m,a[N],ans,Mid,tre[N<<2],mod[N][3],q;
 12 
 13 bool lzy[N<<2],sig[N<<2];
 14 
 15 inline int read()
 16 {
 17     int x=0;
 18     char ch=getchar();
 19     while(!isdigit(ch))
 20         ch=getchar();
 21     while(isdigit(ch))
 22         x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
 23     return x;
 24 }
 25 
 26 void build(int t,int l,int r)
 27 {
 28     if(l==r)
 29     {
 30         tre[t]=(a[l]>=Mid);
 31         return;
 32     }
 33     int mid=(l+r)>>1;
 34     build(t<<1,l,mid);
 35     build((t<<1)+1,mid+1,r);
 36     tre[t]=tre[t<<1]+tre[(t<<1)+1];
 37 }
 38 
 39 inline void down(int t,int l,int r)
 40 {
 41     if(!lzy[t])
 42         return;
 43     int mid=(l+r)>>1;
 44     lzy[t<<1]=lzy[(t<<1)+1]=1;
 45     sig[t<<1]=sig[(t<<1)+1]=sig[t];
 46     tre[t<<1]=(mid-l+1)*sig[t];
 47     tre[(t<<1)+1]=(r-mid)*sig[t];
 48     lzy[t]=0;
 49 }
 50 
 51 int query(int t,int l,int r,int ll,int rr)
 52 {
 53     if(ll<=l&&r<=rr)
 54         return tre[t];
 55     down(t,l,r);
 56     int mid=(l+r)>>1;
 57     if(ll<=mid)
 58     {
 59         if(rr>mid)
 60             return query(t<<1,l,mid,ll,rr)+query((t<<1)+1,mid+1,r,ll,rr);
 61         else
 62             return query(t<<1,l,mid,ll,rr);
 63     }
 64     else
 65         return query((t<<1)+1,mid+1,r,ll,rr);
 66 }
 67 
 68 void modify(int t,int l,int r,int ll,int rr,int x)
 69 {
 70     if(ll<=l&&r<=rr)
 71     {
 72         lzy[t]=1;
 73         sig[t]=x;
 74         tre[t]=(r-l+1)*x;
 75         return;
 76     }
 77     down(t,l,r);
 78     if(ll<=dmid)
 79         modify(t<<1,l,dmid,ll,rr,x);
 80     if(rr>dmid)
 81         modify((t<<1)+1,dmid+1,r,ll,rr,x);
 82     tre[t]=tre[t<<1]+tre[(t<<1)+1];
 83 }
 84 
 85 inline int check()
 86 {
 87     build(1,1,n);
 88     memset(lzy,0,sizeof lzy);
 89     int cnt,ll,rr;
 90     for(int i=1;i<=m;++i)
 91     {
 92         ll=mod[i][1],rr=mod[i][2];
 93         cnt=query(1,1,n,ll,rr);
 94         if(mod[i][0])
 95         {
 96             if(cnt)
 97                 modify(1,1,n,ll,ll+cnt-1,1);
 98             modify(1,1,n,ll+cnt,rr,0);
 99         }
100         else
101         {
102             modify(1,1,n,ll,rr-cnt,0);
103             if(cnt)
104                 modify(1,1,n,rr-cnt+1,rr,1);
105         }
106     }
107     return query(1,1,n,q,q);
108 }
109 
110 int main()
111 {
112     n=read();m=read();
113     for(int i=1;i<=n;++i)
114         a[i]=read();
115     for(int i=1;i<=m;++i)
116         mod[i][0]=read(),mod[i][1]=read(),mod[i][2]=read();
117     q=read();
118     int l=1,r=n;
119     while(l<=r)
120     {
121         Mid=(l+r)>>1;
122         if(check())
123         {
124             ans=Mid;
125             l=Mid+1;
126         }
127         else
128             r=Mid-1;
129     }
130     cout<<ans;
131     return 0;
132 }

参考资料:

题解 P2824 【[HEOI2016]排序】

posted @ 2020-09-18 10:17  千叶繁华  阅读(194)  评论(0编辑  收藏  举报