[bzoj1176]Mokia
CDQ分治。
注意树状数组不要直接 memset或暴力赋值,这里重新对每个节点add一次相反数就行了。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct quest{
int opt;
int id,x,y,sum;
}q[N];
bool cmpx(const quest a,const quest b){
if(a.x==b.x)
if(a.y==b.y)return a.id<b.id;
return a.y<b.y;
else return a.x<b.x;
}
bool cmpy(const quest a,const quest b){
if(a.y==b.y)return a.id<b.id;
return a.y<b.y;
}
int n,cnt,s,w,m;
inline void ins1(int x,int y,int a,int id){
++cnt;q[cnt].x=x,q[cnt].y=y,q[cnt].sum=a,q[cnt].opt=1,q[cnt].id=id;
}
inline void ins2(int x1,int y1,int x2,int y2,int id){
++cnt;q[cnt].x=x1-1,q[cnt].y=y1-1,q[cnt].sum=1,q[cnt].opt=2,q[cnt].id=id;
++cnt;q[cnt].x=x2,q[cnt].y=y2,q[cnt].sum=1,q[cnt].opt=2,q[cnt].id=id;
++cnt;q[cnt].x=x1-1,q[cnt].y=y2,q[cnt].sum=-1,q[cnt].opt=2,q[cnt].id=id;
++cnt;q[cnt].x=x2,q[cnt].y=y1-1,q[cnt].sum=-1,q[cnt].opt=2,q[cnt].id=id;
}
int op[N];
int ans[N];
#define lowbit(x) ((x)&(-x))
int t[N];
inline void add(int x,int sum){
for(;x<=m;x+=lowbit(x))t[x]+=sum;
}
inline int qry(int x){
int ret=0;
for(;x;x-=lowbit(x))ret+=t[x];
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 j=mid+1;
for(int i=l;i<=mid;i++){
while(j<=r&&q[j].y<q[i].y){
if(q[j].opt==2)
ans[q[j].id]+=q[j].sum*qry(q[j].id);
j++;
}
if(q[i].opt==1)add(q[i].id,q[i].sum);
}
while(j<=r){
if(q[j].opt==2)
ans[q[j].id]+=q[j].sum*qry(q[j].id);
j++;
}
for(int i=l;i<=mid;i++)
if(q[i].opt==1)add(q[i].id,-1*q[i].sum);
sort(q+l,q+r+1,cmpy);
}
int main()
{
scanf("%d%d",&s,&w);
m=0;
while(true){
int opt=0;
scanf("%d",&opt);
op[m+1]=opt;
if(opt==3)break;
if(opt==1){
int x,y,a;
scanf("%d%d%d",&x,&y,&a);
ins1(x,y,a,++m);
}
if(opt==2){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
ins2(x1,y1,x2,y2,++m);
ans[m]=s*(x2-x1+1)*(y2-y1+1);
}
}
sort(q+1,q+cnt+1,cmpx);
cdq(1,cnt);
for(int i=1;i<=m;i++)if(op[i]==2){
printf("%d\n",ans[i]);
}
}