bzoj 1176: [Balkan2007]Mokia
来源:互联网 发布:python大神 编辑:程序博客网 时间:2024/05/18 02:17
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范围
CDQ分治。。我们读入所有操作后按照操作时间排序【其实就是读入顺序】。这样可以保证右边不对左边产生影响
然后solve(l,r)分成solve(l,mid)和(mid+1,r)来做,把左边的修改按照x排序。然后用树状数组记录y轴上的总和。
每个询问(x1,y1) (x2,y2)变成(1,y1)(x1-1,y2)和(1,y1)(x2,y2),然后把左边扫两遍把右边的询问计算两次就可以了。
然后再递归处理
<pre name="code" class="cpp">#include<cstdio>#include<algorithm>using namespace std;struct add{ int s; int x,y,a; int x1,y1,x2,y2; int p;}a[200001],b[200001],c[200001];int ans[200001];inline bool cmp1(add x,add y){ if(x.x<y.x) return true; //if(x.x==y.x&&x.y<y.y) // return true; return false;}inline bool cmp2(add x,add y){ if(x.x1<y.x1) return true; return false;}inline bool cmp3(add x,add y){ if(x.x2<y.x2) return true; return false;}int tr[2000001];int w;inline int lowbit(int x){ return x&(-x);}inline void add(int x,int xx){ int i; for(i=x;i<=w;i+=lowbit(i)) tr[i]+=xx;}inline int ask(int x){ int i; int ans=0; for(i=x;i>=1;i-=lowbit(i)) ans+=tr[i]; return ans;}inline void solve(int l,int r){ if(l!=r) { int mid=(l+r)/2; solve(l,mid); solve(mid+1,r); int i; int p=0; for(i=l;i<=mid;i++) { if(a[i].s==1) { p++; b[p]=a[i]; } } sort(b+1,b+1+p,cmp1); int p1=0; for(i=mid+1;i<=r;i++) { if(a[i].s==2) { p1++; c[p1]=a[i]; } } sort(c+1,c+1+p1,cmp2); int i1=1,i2=1; while(i1<=p&&i2<=p1) { if(b[i1].x<=c[i2].x1-1) { add(b[i1].y,b[i1].a); i1++; } else { ans[c[i2].p]-=(ask(c[i2].y2)-ask(c[i2].y1-1)); i2++; } } if(i2<=p1) for(i=i2;i<=p1;i++) ans[c[i].p]-=(ask(c[i].y2)-ask(c[i].y1-1)); for(i=1;i<=i1-1;i++) add(b[i].y,-b[i].a); sort(c+1,c+1+p1,cmp3); i1=1; i2=1; while(i1<=p&&i2<=p1) { if(b[i1].x<=c[i2].x2) { add(b[i1].y,b[i1].a); i1++; } else { ans[c[i2].p]+=(ask(c[i2].y2)-ask(c[i2].y1-1)); i2++; } } if(i2<=p1) for(i=i2;i<=p1;i++) ans[c[i].p]+=(ask(c[i].y2)-ask(c[i].y1-1)); for(i=1;i<=i1-1;i++) add(b[i].y,-b[i].a); }}int main(){ int s; scanf("%d%d",&s,&w); int x; int p=0; scanf("%d",&x); while(x!=3) { if(x==1) { p++; a[p].s=1; scanf("%d%d%d",&a[p].x,&a[p].y,&a[p].a); } else { p++; a[p].s=2; scanf("%d%d%d%d",&a[p].x1,&a[p].y1,&a[p].x2,&a[p].y2); } a[p].p=p; scanf("%d",&x); } // sort(a+1,a+1+p1,cmp1); solve(1,p); int i; for(i=1;i<=p;i++) if(a[i].s==2) printf("%d\n",ans[i]+(a[i].x2-a[i].x1+1)*(a[i].y2-a[i].y1+1)*s); return 0;}
0 0
- 【BZOJ 1176】 [Balkan2007]Mokia
- bzoj 1176: [Balkan2007]Mokia
- BZOJ 1176 [Balkan2007] Mokia
- bzoj 1176: [Balkan2007]Mokia
- bzoj 1176 [Balkan2007]Mokia
- bzoj 1176: [Balkan2007]Mokia
- 【分治】 BZOJ 1176 [Balkan2007]Mokia
- BZOJ 1176: [Balkan2007]Mokia CDQ
- BZOJ 1176 [Balkan2007]Mokia CDQ分治
- BZOJ 1176: [Balkan2007]Mokia CDQ分治
- bzoj 1176: [Balkan2007]Mokia 【CDQ分治】
- bzoj 1176: [Balkan2007]Mokia(cdq分治)
- 【BZOJ 1176】 [Balkan2007]Mokia cdq分治
- BZOJ 1176: [Balkan2007]Mokia (CDQ分治)
- BZOJ 1176: [Balkan2007]Mokia/2683: 简单题
- 1176: [Balkan2007]Mokia
- BZOJ 1176([Balkan2007]Mokia-CDQ分治-分治询问)
- [BZOJ 1176]Balkan2007 Mokia cdq分治一血!
- C语言及程序设计.第十一课.项目2.分离整数和小数部分
- iOS 中的 url 编码问题
- JavaSript模块规范 - AMD规范与CMD规范介绍
- HDOJ 1271 小希的迷宫(并查集+判断环)
- JS禁用浏览器退格键
- bzoj 1176: [Balkan2007]Mokia
- TCP/IP体系结构
- 函数调用方式关键字解析
- 程序员最爱的的 9 款文本编辑器
- Google Earth与ArcGIS数据交互(二)
- [LinkedIn]Implement Find and replace (find given pattern and replace it with a given string)
- JS获取浏览器相关的宽高总结
- 从mysql数据库中导入数据到solr4.5
- [POJ3415]Common Substrings && 后缀数组+单调栈