学习二进制分组
题目本身可以看成二维平面上的问题,转成切比雪夫距离后就是矩形和了
二进制分组是将每个修改添加到末尾,然后从后往前二进制下进位合并,这样最多同时有$log n$组,每个修改只会被合并$log n$次。再用一个$log$代价在每次询问时把答案合并起来即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 #define vpii vector<pair<int,int> > 6 using namespace std; 7 const int N=150005,M=1e7,K=20,inf=1e9; 8 int n,m,nm,t1,t2,pt,pw,a[N],bin[M+70],vis[M+70]; 9 int root[K][N],val[M+70],son[M+70][2]; vpii ve[20]; 10 char rd[10]; 11 void Modify(int &nde,int lst,int l,int r,int tsk) 12 { 13 nde=bin[pt--],vis[nde]=false; 14 val[nde]=val[lst]+1; 15 son[nde][0]=son[lst][0]; 16 son[nde][1]=son[lst][1]; 17 if(l==r) return; int mid=(l+r)>>1; 18 if(tsk<=mid) Modify(son[nde][0],son[lst][0],l,mid,tsk); 19 else Modify(son[nde][1],son[lst][1],mid+1,r,tsk); 20 } 21 void Delete(int nde,int l,int r) 22 { 23 if(vis[nde]) return; 24 bin[++pt]=nde,vis[nde]=true; 25 int mid=(l+r)>>1; 26 Delete(son[nde][0],l,mid); 27 Delete(son[nde][1],mid+1,r); 28 val[nde]=son[nde][0]=son[nde][1]=0; 29 } 30 void Insert(int x,int y) 31 { 32 ve[++pw].push_back(make_pair(x,y)); 33 Modify(root[pw][1],root[pw][0],1,nm,y); 34 while(pw>1&&ve[pw].size()==ve[pw-1].size()) 35 { 36 int t1=0,t2=0,sz=ve[pw].size(); vpii tmp; 37 for(int i=1;i<=sz;i++) Delete(root[pw][i],1,nm); 38 for(int i=1;i<=sz;i++) Delete(root[pw-1][i],1,nm); 39 while(t1<sz||t2<sz) 40 if(t1<sz&&(t2==sz||ve[pw-1][t1]<ve[pw][t2])) 41 tmp.push_back(ve[pw-1][t1++]),Modify(root[pw-1][t1+t2],root[pw-1][t1+t2-1],1,nm,ve[pw-1][t1-1].second); 42 else 43 tmp.push_back(ve[pw][t2++]),Modify(root[pw-1][t1+t2],root[pw-1][t1+t2-1],1,nm,ve[pw][t2-1].second); 44 ve[pw-1]=tmp,ve[pw--].clear(); 45 } 46 } 47 int Ask(int nl,int nr,int l,int r,int ll,int rr) 48 { 49 if(l>=ll&&r<=rr) 50 return val[nr]-val[nl]; 51 else 52 { 53 int ret=0,mid=(l+r)>>1; 54 if(mid>=ll) ret+=Ask(son[nl][0],son[nr][0],l,mid,ll,rr); 55 if(mid<rr) ret+=Ask(son[nl][1],son[nr][1],mid+1,r,ll,rr); 56 return ret; 57 } 58 } 59 int Query(int x,int y,int k) 60 { 61 int ret=0; 62 for(int i=1;i<=pw;i++) 63 { 64 int ll=lower_bound(ve[i].begin(),ve[i].end(),make_pair(x-k,0))-ve[i].begin(); 65 int rr=lower_bound(ve[i].begin(),ve[i].end(),make_pair(x+k,inf))-ve[i].begin(); 66 ret+=Ask(root[i][ll],root[i][rr],1,nm,max(y-k,1),min(y+k,nm)); 67 } 68 return ret; 69 } 70 int main() 71 { 72 scanf("%d%d",&n,&m); 73 vis[0]=true,nm=160000; 74 for(int i=1;i<=M;i++) 75 bin[++pt]=i,vis[i]=true; 76 for(int i=1;i<=n;i++) 77 scanf("%d",&a[i]),Insert(a[i]+i,a[i]-i+n); 78 for(int i=1;i<=m;i++) 79 { 80 scanf("%s%d%d",rd,&t1,&t2); 81 if(rd[0]=='M') a[t1]=t2,Insert(t2+t1,t2-t1+n); 82 else printf("%d ",Query(a[t1]+t1,a[t1]-t1+n,t2)); 83 } 84 return 0; 85 }