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