BZOJ 4066 简单题
2018.03.07
2018.03.07
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
1 x y A ($1 \le x,y \le N$,A是正整数) 将格子x,y里的数字加上A 2 x1 y1 x2 y2 ($1 \le x1 \le x2 \le N,1 \le y1 \le y2 \le N$) 输出x1 y1 x2 y2这个矩形内的数字和
二维K-D Tree+Lazy标记。
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 300000
int n,md,ia,ib,ic,id,LA,rt,tot;
int sw;
struct node
{
int v[2],mx[2],mn[2],ls,rs,sm,vl;
bool operator<(const node &tg)const{return v[sw]==tg.v[sw]?v[sw^1]<tg.v[sw^1]:v[sw]<tg.v[sw];}
}p[N];
inline void pushup(int pos)
{
p[pos].sm=p[p[pos].ls].sm+p[p[pos].rs].sm+p[pos].vl;
p[pos].mx[0]=max(max(p[p[pos].ls].mx[0],p[p[pos].rs].mx[0]),p[pos].v[0]);
p[pos].mx[1]=max(max(p[p[pos].ls].mx[1],p[p[pos].rs].mx[1]),p[pos].v[1]);
p[pos].mn[0]=min(min(p[p[pos].ls].mn[0],p[p[pos].rs].mn[0]),p[pos].v[0]);
p[pos].mn[1]=min(min(p[p[pos].ls].mn[1],p[p[pos].rs].mn[1]),p[pos].v[1]);
}
int rebuild(int l,int r,int now)
{
if(l>r) return 0;
int mid=(l+r)>>1;
sw=now;
nth_element(p+l,p+mid,p+r+1);
p[mid].ls=rebuild(l,mid-1,now^1),p[mid].rs=rebuild(mid+1,r,now^1);
pushup(mid);
return mid;
}
void insert(int &pos,int x,int y,int z,int now)
{
if(!pos)
{
pos=++tot;
p[pos].v[0]=x,p[pos].v[1]=y;
p[pos].sm=p[pos].vl=z;
pushup(pos);
return;
}
if(p[pos].v[0]==x&&p[pos].v[1]==y) p[pos].vl+=z;
else if(now==0)
{
if(p[pos].v[now]<x) insert(p[pos].ls,x,y,z,now^1);
else insert(p[pos].rs,x,y,z,now^1);
}
else if(now==1)
{
if(p[pos].v[now]<y) insert(p[pos].ls,x,y,z,now^1);
else insert(p[pos].rs,x,y,z,now^1);
}
pushup(pos);
}
void query(int pos,int W,int A,int S,int D)
{
if(!pos||p[pos].mn[0]>D||p[pos].mx[0]<A||p[pos].mn[1]>W||p[pos].mx[1]<S) return;
if(p[pos].mn[0]>=A&&p[pos].mx[0]<=D&&p[pos].mn[1]>=S&&p[pos].mx[1]<=W) {LA+=p[pos].sm;return;}
if(p[pos].v[0]>=A&&p[pos].v[0]<=D&&p[pos].v[1]>=S&&p[pos].v[1]<=W) LA+=p[pos].vl;
query(p[pos].ls,W,A,S,D);
query(p[pos].rs,W,A,S,D);
}
int main()
{
p[0].mn[0]=p[0].mn[1]=0x3f3f3f3f,p[0].mx[0]=p[0].mx[1]=-0x3f3f3f3f;
srand(1026);
scanf("%d",&n);
while(scanf("%d",&md),md!=3)
{
if(!(rand()%4000)) rt=rebuild(1,tot,0);
switch(md)
{
case 1:scanf("%d%d%d",&ia,&ib,&ic),ia^=LA,ib^=LA,ic^=LA,insert(rt,ia,ib,ic,0);break;
case 2:scanf("%d%d%d%d",&ia,&ib,&ic,&id),ia^=LA,ib^=LA,ic^=LA,id^=LA,LA=0,query(rt,id,ia,ib,ic),printf("%d\n",LA);break;
}
}
return 0;
}