[Comet1173]最简单的题

称区间$[l,r]$的"信息"为其的答案和第一个、最后一个大于$x$的位置,显然通过$[l,mid]$和$[mid+1,r]$的信息可以$o(1)$合并得到$[l,r]$的信息

考虑分块,将其按$K$的块大小分块,区间查询时求出散块每一个位置的信息(将其看作一个区间)和每一个整块的信息,之后即可$o(K+\frac{n}{K})$合并得到整个块的信息

下面的问题即如何求整块的信息,对整块维护:1.排序后的结果;2.当$x$为块中每一个元素时的信息;3.[luogu6466]分散层叠算法的做法4所维护的分治结构(将$x$作为小于等于$x$的最大元素即可)

对于排序后的结果时间复杂度为$o(n\log n)-o(K)$(单点修改即插入排序),当得到排序后的结果后,该块的"信息"也可以在$o(K)$的复杂度内得到——

关于答案,只需要从小到大枚举元素,每一次即加入一个元素,通过链表支持合并即可

关于第一个和最后一个大于$x$的位置,维护排序后的序列位置的后缀最小值和最大值即可

由此即可支持单点修改,单次复杂度为$o(K)$,取$K=\sqrt{n}$单次复杂度即$o(\sqrt{n})$

时间复杂度为$o(n\log n)-o(\sqrt{n})$

(由于该oj似乎不支持提交,与某个通过的代码拍过,正确性大概是能保证的,速度大约是其1.5倍)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 300005
  4 #define K 600
  5 #define D 3
  6 #define ll long long
  7 #define L (k<<1)
  8 #define R (L+1)
  9 #define mid (l+r>>1)
 10 struct Data{
 11     int l,r;
 12     ll ans;
 13 }ans[N];
 14 int n,m,k,p,x,y,z,num[21],a[N],bl[N],st[K],ed[K],id[N];
 15 int read(){
 16     int x=0;
 17     char c=getchar();
 18     while ((c<'0')||(c>'9'))c=getchar();
 19     while ((c>='0')&&(c<='9')){
 20         x=x*10+(c-'0');
 21         c=getchar();
 22     }
 23     return x;
 24 }
 25 void write(ll x,char c='\0'){
 26     while (x){
 27         num[++num[0]]=x%10;
 28         x/=10;
 29     }
 30     if (!num[0])putchar('0');
 31     while (num[0])putchar(num[num[0]--]+'0');
 32     putchar(c);
 33 }
 34 bool cmp(int x,int y){
 35     return a[x]<a[y];
 36 }
 37 bool Cmp(int x,int y){
 38     return a[x]<=y;
 39 }
 40 Data merge(Data x,Data y);
 41 namespace Rope{
 42     int n,vis[N],l[N],r[N];
 43     ll ans;
 44     void init(int nn){
 45         n=nn;
 46         for(int i=0;i<=n+1;i++)vis[i]=0;
 47         for(int i=1;i<=n;i++)l[i]=r[i]=i;
 48     }
 49     void link(int x){
 50         ans+=(ll)(x-l[x]+1)*(r[x+1]-x);
 51         l[r[x+1]]=l[x],r[l[x]]=r[x+1];
 52     }
 53     ll add(int x){
 54         ans=vis[x]=1;
 55         if (vis[x-1])link(x-1);
 56         if (vis[x+1])link(x);
 57         return ans;
 58     }
 59 };
 60 namespace Seg{
 61     int Pos[2],b[K<<2][K],pos[K<<2][K][2];
 62     void get(int k,int x){
 63         b[k][0]=0;
 64         for(int i=st[x];i<=ed[x];i++)b[k][++b[k][0]]=id[i];
 65     }
 66     void up(int k){
 67         b[k][0]=0;
 68         int x=1,y=1;
 69         while ((x<=b[L][0])||(y<=b[R][0])){
 70             if ((x<=b[L][0])&&((y>b[R][0])||(cmp(b[L][x],b[R][y])))){
 71                 b[k][++b[k][0]]=b[L][x];
 72                 pos[k][b[k][0]][0]=x;
 73                 pos[k][b[k][0]][1]=0;
 74                 x+=D;
 75             }
 76             else{
 77                 b[k][++b[k][0]]=b[R][y];
 78                 pos[k][b[k][0]][0]=0;
 79                 pos[k][b[k][0]][1]=y;
 80                 y+=D;
 81             }
 82         }
 83         memset(Pos,0,sizeof(Pos));
 84         for(int i=1;i<=b[k][0];i++)
 85             for(int p=0;p<2;p++){
 86             if (pos[k][i][p])Pos[p]=pos[k][i][p];
 87             pos[k][i][p]=Pos[p];
 88         }
 89     }
 90     void build(int k,int l,int r){
 91         if (l==r){
 92             get(k,l);
 93             return;
 94         }
 95         build(L,l,mid);
 96         build(R,mid+1,r);
 97         up(k);
 98     }
 99     void update_point(int k,int l,int r,int x){
100         if (l==r){
101             get(k,x);
102             return;
103         }
104         if (x<=mid)update_point(L,l,mid,x);
105         else update_point(R,mid+1,r,x);
106         up(k);
107     }
108     void query_seg(int k,int l,int r,int x,int y,int z,int w){
109         if ((l>y)||(x>r))return;
110         if (!z){
111             ans[0]=merge(ans[0],Data{0,0,0});
112             return;
113         }
114         if (l==r){
115             ans[0]=merge(ans[0],ans[b[k][z]]);
116             return;
117         }
118         int zl=pos[k][z][0],zr=pos[k][z][1];
119         while ((zl<b[L][0])&&(Cmp(b[L][zl+1],w)))zl++;
120         while ((zr<b[R][0])&&(Cmp(b[R][zr+1],w)))zr++;
121         query_seg(L,l,mid,x,y,zl,w);
122         query_seg(R,mid+1,r,x,y,zr,w);
123     }
124     void query(int l,int r,int x){
125         if (l>r)return;
126         query_seg(1,1,bl[n],l,r,lower_bound(b[1]+1,b[1]+b[1][0]+1,x,Cmp)-b[1]-1,x);
127     }
128 };
129 Data merge(Data x,Data y){
130     Data ans;
131     ans.ans=x.ans+y.ans;
132     if ((x.r<0)&&(y.r<0)){
133         ans.l=x.l+y.l,ans.r=-1;
134         ans.ans+=(ll)x.l*y.l;
135         return ans;
136     }
137     if (x.r<0){
138         ans.l=x.l+y.l,ans.r=y.r;
139         ans.ans+=(ll)x.l*y.l;
140         return ans;
141     }
142     if (y.r<0){
143         ans.l=x.l,ans.r=x.r+y.l;
144         ans.ans+=(ll)x.r*y.l;
145         return ans;
146     }
147     ans.l=x.l,ans.r=y.r;
148     ans.ans+=(ll)x.r*y.l;
149     return ans;
150 }
151 void upd(int k,int x){
152     for(int i=st[k];i<=ed[k];i++)
153         if (id[i]==x){
154             x=i;
155             break;
156         }
157     int s=id[x];
158     for(int i=x;i<ed[k];i++)id[i]=id[i+1];
159     for(int i=st[k];i<ed[k];i++)
160         if (cmp(s,id[i])){
161             for(int j=ed[k];j>i;j--)id[j]=id[j-1];
162             id[i]=s;
163             return;
164         }
165     id[ed[k]]=s;
166 }
167 void calc(int k){
168     ans[id[ed[k]]].l=ed[k]-st[k]+1,ans[id[ed[k]]].r=-1;
169     int l=id[ed[k]]-st[k],r=ed[k]-id[ed[k]];
170     for(int i=ed[k]-1;i>=st[k];i--){
171         ans[id[i]].l=l,ans[id[i]].r=r;
172         l=min(l,id[i]-st[k]),r=min(r,ed[k]-id[i]);
173     }
174     Rope::init(ed[k]-st[k]+1);
175     ll sum=0;
176     for(int i=st[k];i<=ed[k];i++){
177         sum+=Rope::add(id[i]-st[k]+1);
178         ans[id[i]].ans=sum;
179     }
180 }
181 int main(){
182     n=read(),m=read(),k=(int)sqrt(n);
183     for(int i=1;i<=n;i++)a[i]=read();
184     for(int i=1;i<=n;i++){
185         id[i]=i;
186         bl[i]=(i-1)/k+1;
187         if (!st[bl[i]])st[bl[i]]=i;
188         ed[bl[i]]=i;
189     }
190     for(int i=1;i<=bl[n];i++){
191         sort(id+st[i],id+ed[i]+1,cmp);
192         calc(i);
193     }
194     Seg::build(1,1,bl[n]);
195     for(int i=1;i<=m;i++){
196         p=read(),x=read(),y=read();
197         if (p==1){
198             a[x]=y;
199             upd(bl[x],x);
200             calc(bl[x]);
201             Seg::update_point(1,1,bl[n],bl[x]);
202         }
203         else{
204             z=read();
205             ans[0]=Data{0,-1,0};
206             if (bl[x]==bl[y]){
207                 for(int j=x;j<=y;j++)
208                     if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
209                     else ans[0]=merge(ans[0],Data{1,-1,1});
210             }
211             else{
212                 for(int j=x;j<=ed[bl[x]];j++)
213                     if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
214                     else ans[0]=merge(ans[0],Data{1,-1,1});
215                 Seg::query(bl[x]+1,bl[y]-1,z);
216                 for(int j=st[bl[y]];j<=y;j++)
217                     if (a[j]>z)ans[0]=merge(ans[0],Data{0,0,0});
218                     else ans[0]=merge(ans[0],Data{1,-1,1});
219             }
220             write(ans[0].ans,'\n');
221         }
222     }
223     return 0;
224 } 
View Code

 

posted @ 2021-09-07 08:59  PYWBKTDA  阅读(56)  评论(0编辑  收藏  举报