解题:BZOJ 2989 数列

题面

学习二进制分组

题目本身可以看成二维平面上的问题,转成切比雪夫距离后就是矩形和了

二进制分组是将每个修改添加到末尾,然后从后往前二进制下进位合并,这样最多同时有$\log n$组,每个修改只会被合并$\log n$次。再用一个$log$代价在每次询问时把答案合并起来即可

 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\n",Query(a[t1]+t1,a[t1]-t1+n,t2));
83     }
84     return 0;
85 }
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/10491818.html