您的位置:首页 > 其它

bzoj1176 [Balkan2007]Mokia(CDQ二维平面)

2017-12-14 15:20 381 查看

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

Sample Output

3

5


[Submit][Status][Discuss]

分析:

CDQ分治

详情请参考bzoj2683

唯一不同点是有初始值

然而初始值是面向全体的,所以我们直接在ans上加上(矩阵大小*S)即可

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N=2000010;
struct node{
int type,x,ya,yb,id,z;
};
node po[N<<1];
int tot,totx=0,ans[10010],t
;
int n,S;

int get(int xa,int ya,int xb,int yb) {return (xb-xa+1)*(yb-ya+1)*S;}

void add(int x,int z){for (int i=x;i<=n;i+=(i&(-i))) t[i]+=z;}
int ask(int x) {int ans=0;for (int i=x;i>0;i-=(i&(-i))) ans+=t[i];return ans;}

int cmp(const node &a,const node &b)
{
if (a.x!=b.x) return a.x<b.x;
else return a.type<b.type;
}

void CDQ(int L,int R)
{
if (L==R) return;
int M=(L+R)>>1;
CDQ(L,M); CDQ(M+1,R);

sort(po+L,po+M+1,cmp);
sort(po+M+1,po+R+1,cmp);

int t1=L,t2=M+1,last=0;
while (t2<=R)
{
while (t1<=M&&po[t1].type!=1) t1++;
while (t2<=R&&po[t2].type==1) t2++;
if (t1<=M&&po[t1].x<=po[t2].x)
{
add(po[t1].ya,po[t1].z);
last=t1++;
}
else if (t2<=R)
{
if (po[t2].type==2) ans[po[t2].id]-=ask(po[t2].yb)-ask(po[t2].ya-1),t2++;
else ans[po[t2].id]+=ask(po[t2].yb)-ask(po[t2].ya-1),t2++;
}
}

for (int i=L;i<=last;i++)
if (po[i].type==1) add(po[i].ya,-po[i].z);
}

int main()
{
scanf("%d%d",&S,&n);
for (;;)
{
int opt,xa,ya,xb,yb,z;
scanf("%d",&opt);
if (opt==1)
{
tot++;
scanf("%d%d%d",&xa,&ya,&z);
po[tot].type=1; po[tot].x=xa; po[tot].ya=ya; po[tot].z=z;
}
else if (opt==2)
{
scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
tot++; totx++;
po[tot].type=2; po[tot].x=xa-1;
po[tot].ya=ya; po[tot].yb=yb; po[tot].id=totx;
tot++;
po[tot].type=3; po[tot].x=xb;
po[tot].ya=ya; po[tot].yb=yb; po[tot].id=totx;
ans[totx]=get(xa,ya,xb,yb);
}
else break;
}

CDQ(1,tot);

for (int i=1;i<=totx;i++) printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: