题意
要求资瓷下列操作:
1 x y z把(x,y)加上z
2 x1 y1 x2 y2求矩形x1 y1 x2 y2的权值和
n<=500000,x,y<=n,q<=200000
分析
首先可以把一个询问用容斥原理拆成四个询问,然后在cdq分治中二分一个横坐标mid,然后把操作从前往后扫一遍,若是修改操作且横坐标不大于mid则处理,若是询问操作且横坐标大于mid则处理;然后把操作按照横坐标分成左右两部分递归处理即可。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 500005
using namespace std;
int c[N],n,m,num,ans[N];
struct que{int x,y,z,op,id,ans,val;}q[N*4],tmp[N*4];
int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void ins(int x,int y)
{
while (x<=n)
{
c[x]+=y;
x+=x&(-x);
}
}
int query(int x)
{
int ans=0;
while (x)
{
ans+=c[x];
x-=x&(-x);
}
return ans;
}
void cdq(int l,int r,int L,int R)
{
if (l>=r) return;
if (L==R)
{
for (int i=l;i<=r;i++)
if (q[i].op==1) ins(q[i].y,q[i].z);
else q[i].ans+=query(q[i].y);
for (int i=l;i<=r;i++)
if (q[i].op==1) ins(q[i].y,-q[i].z);
return;
}
int mid=(L+R)/2,s=0;
for (int i=l;i<=r;i++)
if (q[i].op==1)
{
if (q[i].x<=mid)
{
ins(q[i].y,q[i].z);
s++;
}
}else
{
if (q[i].x>mid) q[i].ans+=query(q[i].y);
else s++;
}
for (int i=l;i<=r;i++)
if (q[i].op==1&&q[i].x<=mid) ins(q[i].y,-q[i].z);
int i=l,j=l+s;
for (int k=l;k<=r;k++)
if (q[k].x<=mid) tmp[i++]=q[k];
else tmp[j++]=q[k];
for (int k=l;k<=r;k++)
q[k]=tmp[k];
cdq(l,i-1,L,mid);
cdq(i,r,mid+1,R);
}
int main()
{
//freopen("2683.in","r",stdin);
//freopen("test.out","w",stdout);
n=read();
while (1)
{
int op=read();
if (op==3) break;
if (op==1)
{
int x=read(),y=read(),z=read();
m++;
q[m].op=op;q[m].x=x;q[m].y=y;q[m].z=z;
}else
{
int x1=read(),y1=read(),x2=read(),y2=read();
num++;
m++;
q[m].op=2;q[m].id=num;q[m].x=x2;q[m].y=y2;q[m].val=1;
if (q[m].x==0) m--;
m++;
q[m].op=2;q[m].id=num;q[m].x=x1-1;q[m].y=y2;q[m].val=-1;
if (q[m].x==0) m--;
m++;
q[m].op=2;q[m].id=num;q[m].x=x2;q[m].y=y1-1;q[m].val=-1;
if (q[m].x==0) m--;
m++;
q[m].op=2;q[m].id=num;q[m].x=x1-1;q[m].y=y1-1;q[m].val=1;
if (q[m].x==0) m--;
}
}
cdq(1,m,1,n);
for (int i=1;i<=m;i++)
if (q[i].op==2) ans[q[i].id]+=q[i].val*q[i].ans;
for (int i=1;i<=num;i++)
printf("%d\n",ans[i]);
return 0;
}