【BZOJ1176】[Balkan2007]Mokia/【BZOJ2683】简单题 cdq分治
【BZOJ1176】[Balkan2007]Mokia
Description
维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
Input
第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小
接下来每行为一下三种输入之一(不包含引号):
"1 x y a"
"2 x1 y1 x2 y2"
"3"
输入1:你需要把(x,y)(第x行第y列)的格子权值增加a
输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出
输入3:表示输入结束
Output
对于每个输入2,输出一行,即输入2的答案
Sample Input
0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
5
HINT
保证答案不会超过int范围
【BZOJ2683】简单题
题意:和上面一样
题解:依旧是分治思路
我们将询问差分,拆成四个点分别求前缀和,然后将询问和修改一起按横坐标排序;
然后在跑cdq分治的时候,我们一边递归一边按照修改的时间进行归并排序。根据cdq分治的思想,我们在执行区间[l,r]时已经处理完[l,mid]和[mid+1,r]了,那么我们只需要处理[l,mid]中的修改对[mid+1,r]中的询问造成的影响。于是我们在跑归并排序的时候,将[l,mid]中的修改按照纵坐标插入树状数组,然后将[mid+1,r]中的询问按照纵坐标在树状数组上查找,再更新一下答案就好了
这代码我已经不怎么压行了,是不是可读性高了好多。。。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,num,m; const int maxn=200010; struct node { int x,y,org,v,k; }s[maxn]; int p[maxn],q[maxn],tr[maxn*10],ans[maxn]; //p是归并排序的顺序,q是p的复制 bool cmp(node a,node b) { if(a.x==b.x&&a.org==b.org) return a.y<b.y; if(a.x==b.x) return a.org<b.org; return a.x<b.x; } void updata(int a,int val) { for(int i=a;i<=n;i+=i&-i) tr[i]+=val; } int query(int a) { int i,ret=0; for(i=a;i;i-=i&-i) ret+=tr[i]; return ret; } void dfs(int l,int r) { if(l==r) { p[l]=l; return ; } int i,mid=l+r>>1,h1=l,h2=mid+1; dfs(l,mid),dfs(mid+1,r); for(i=l;i<=r;i++) { if(h2<=r&&(h1>mid||s[p[h1]].org>=s[p[h2]].org)) { if(!s[p[h2]].k) ans[s[p[h2]].org]+=s[p[h2]].v*query(s[p[h2]].y); q[i]=p[h2++]; } else { if(s[p[h1]].k) updata(s[p[h1]].y,s[p[h1]].v); q[i]=p[h1++]; } } for(i=l;i<=mid;i++) if(s[p[i]].k) updata(s[p[i]].y,-s[p[i]].v); for(i=l;i<=r;i++) p[i]=q[i]; } int main() { int i,a,b,c,d,e; scanf("%d%d",&a,&n); for(i=1;e!=3;i++) { scanf("%d",&e); if(e==1) { scanf("%d%d%d",&a,&b,&c); s[++num].x=a,s[num].y=b,s[num].org=m,s[num].k=1,s[num].v=c; } if(e==2) { scanf("%d%d%d%d",&a,&b,&c,&d),a--,b--; s[num+1].org=s[num+2].org=s[num+3].org=s[num+4].org=++m; s[num+1].k=s[num+2].k=s[num+3].k=s[num+4].k=0; s[++num].x=a,s[num].y=b,s[num].v=1; s[++num].x=a,s[num].y=d,s[num].v=-1; s[++num].x=c,s[num].y=b,s[num].v=-1; s[++num].x=c,s[num].y=d,s[num].v=1; } } sort(s+1,s+num+1,cmp); dfs(1,num); for(i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }
| 欢迎来原网站坐坐! >原文链接<