577. 蝗灾
输入文件:locust.in 输出文件:locust.out 简单对比
时间限制:2 s 内存限制:128 MiB
【题目描述】
C国国土辽阔,地大物博......但是最近却在闹蝗灾.....
我们可以把C国国土当成一个W×W的矩阵,你会收到一些诸如(X,Y,Z)的信息,代表(X,Y)这个点增多了Z只蝗虫,而由于C国政府机关比较臃肿,为了批复消灭蝗虫的请求需要询问一大堆的问题......每个询问形如(X1,Y1,X2,Y2),询问在(X1,Y1,X2,Y2)范围内有多少蝗虫(请注意询问不会改变区域内的蝗虫数),你作为一个C国的程序员,需要编一个程序快速的回答所有的询问。
NOTICE
C国一开始没有蝗虫。
【输入格式】
输入文件的第一行包括一个整数W,代表C国国土的大小。
第二行有一个整数N,表示事件数。
接下来有N行表示N个事件,以(1 X Y Z)的形式或(2,X1,Y1,X2,Y2)的形式给出,分别代表蝗虫的增加和询问。
【输出格式】
对于每个询问输出一个整数表示需要的结果。
【样例输入】
5
8
2 4 1 4 2
1 3 1 8
1 4 4 4
2 1 3 4 4
1 1 5 1
1 4 4 5
2 2 2 5 4
2 3 2 4 4
【样例输出】
0
4
9
9
【数据范围】
10%的数据满足W<=100,N<=100;
30%的数据满足W<=2000,N<=5000;
50%的数据满足W<=100000,N<=50000;
100%的数据满足W<=500000,N<=200000,每次蝗虫增加数不超过1000;
三维偏序问题的变形,实际上也没变形!
CDQ分治的模板题
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int maxm=5e5+10;
struct node
{
int x,y,z,t,type;
//type:类型,1修改,2查询减,3查询加
//t:时间
//z:修改时为增加的值,查询是为查询的序号
bool operator < (const node & a ) const
{
if(x!=a.x)return x<a.x;
if(y!=a.y)return y<a.y;
if(t!=a.t)return t<a.t;
return 0;
}
}sz[maxn<<2],f[maxn<<2];
int w,n;
int ans[maxn];
int sum[maxm];
void add(int pos,int x)
{
for(int i=pos;i<=w;i+=(-i)&i)sum[i]+=x;
}
int query(int pos)
{
int ret=0;
for(int i=pos;i;i-=(-i)&i)ret+=sum[i];
return ret;
}
void cdq(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>1;
cdq(l,mid);
cdq(mid+1,r);
int q=l,h=mid+1,p=l;
while(q<=mid&&h<=r)
{
if(sz[q]<sz[h])
{
f[p]=sz[q];
if(sz[q].type==1)add(sz[q].y,sz[q].z);
++p;++q;
}
else
{
f[p]=sz[h];
if(sz[h].type!=1)
{
int tp=query(sz[h].y);
if(sz[h].type==2)ans[sz[h].z]-=tp;
else ans[sz[h].z]+=tp;
}
++p;++h;
}
}
while(q<=mid)
{
f[p]=sz[q];
if(sz[q].type==1)add(sz[q].y,sz[q].z);
++p;++q;
}
while(h<=r)
{
f[p]=sz[h];
if(sz[h].type!=1)
{
int tp=query(sz[h].y);
if(sz[h].type==2)ans[sz[h].z]-=tp;
else ans[sz[h].z]+=tp;
}
++p;++h;
}
for(int i=l;i<=mid;++i)if(sz[i].type==1)add(sz[i].y,-sz[i].z);
for(int i=l;i<=r;++i)sz[i]=f[i];
}
int main()
{
freopen("locust.in","r",stdin);
freopen("locust.out","w",stdout);
int tim=0,cnt=0;;
scanf("%d%d",&w,&n);
for(int op,a,b,c,d,i=1;i<=n;++i)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&a,&b,&c);
++tim;
sz[tim].x=a;sz[tim].y=b;sz[tim].z=c;sz[tim].t=tim;
sz[tim].type=1;
}
else
{
scanf("%d%d%d%d",&a,&b,&c,&d);
++cnt;
++tim;
sz[tim].x=c;sz[tim].y=d;sz[tim].z=cnt;sz[tim].type=3;sz[tim].t=tim;
++tim;
sz[tim].x=a-1;sz[tim].y=b-1;sz[tim].z=cnt;sz[tim].type=3;sz[tim].t=tim;
++tim;
sz[tim].x=c;sz[tim].y=b-1;sz[tim].z=cnt;sz[tim].type=2;sz[tim].t=tim;
++tim;
sz[tim].x=a-1;sz[tim].y=d;sz[tim].z=cnt;sz[tim].type=2;sz[tim].t=tim;
}
}
cdq(1,tim);
for(int i=1;i<=cnt;++i)printf("%d
",ans[i]);
return 0;
}
/*
5
8
2 4 1 4 2
1 3 1 8
1 4 4 4
2 1 3 4 4
1 1 5 1
1 4 4 5
2 2 2 5 4
2 3 2 4 4
0
4
9
9
*/