Description
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
1 x y A 将格子x,y里的数字加上A
2 x1 y1 x2 y2 输出x1 y1 x2 y2这个矩形内的数字和
强制在线
1<=N<=500000,操作数不超过200000个,内存限制20M
Solution
真的是简单题。。
不在线可以cdq,在线就kdtree咯
一个小技巧就是定期重构kdtree,或者用平衡因子来判定也行
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define lowbit(x) (x&-x)
const int N=300005;
struct treeNode {int sum,val,son[2],p[2],mx[2],mn[2];} t[N];
int wjp,tot;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int now) {
t[now].sum=t[t[now].son[0]].sum+t[t[now].son[1]].sum+t[now].val;
t[now].mx[0]=t[now].mn[0]=t[now].p[0];
t[now].mx[1]=t[now].mn[1]=t[now].p[1];
if (t[now].son[0]) {
t[now].mx[0]=std:: max(t[t[now].son[0]].mx[0],t[now].mx[0]);
t[now].mx[1]=std:: max(t[t[now].son[0]].mx[1],t[now].mx[1]);
t[now].mn[0]=std:: min(t[t[now].son[0]].mn[0],t[now].mn[0]);
t[now].mn[1]=std:: min(t[t[now].son[0]].mn[1],t[now].mn[1]);
}
if (t[now].son[1]) {
t[now].mx[0]=std:: max(t[t[now].son[1]].mx[0],t[now].mx[0]);
t[now].mx[1]=std:: max(t[t[now].son[1]].mx[1],t[now].mx[1]);
t[now].mn[0]=std:: min(t[t[now].son[1]].mn[0],t[now].mn[0]);
t[now].mn[1]=std:: min(t[t[now].son[1]].mn[1],t[now].mn[1]);
}
}
bool cmp(treeNode a,treeNode b) {
return (a.p[wjp]==b.p[wjp])?(a.p[!wjp]<b.p[!wjp]):(a.p[wjp]<b.p[wjp]);
}
int build(int l,int r,int R) {
int mid=(l+r)>>1; wjp=R;
std:: nth_element(t+l,t+mid,t+r+1,cmp);
t[mid].son[0]=t[mid].son[1]=0;
if (l<mid) t[mid].son[0]=build(l,mid-1,!R);
if (mid<r) t[mid].son[1]=build(mid+1,r,!R);
push_up(mid); return mid;
}
bool check(int now,int x1,int y1,int x2,int y2) {
if (x2<t[now].mn[0]||x1>t[now].mx[0]) return false;
if (y2<t[now].mn[1]||y1>t[now].mx[1]) return false;
return true;
}
int query(int now,int x1,int y1,int x2,int y2,int R) {
if (t[now].mn[0]>=x1&&t[now].mx[0]<=x2&&t[now].mn[1]>=y1&&t[now].mx[1]<=y2) return t[now].sum;
int res=0;
if (t[now].p[0]>=x1&&t[now].p[0]<=x2&&t[now].p[1]>=y1&&t[now].p[1]<=y2) res+=t[now].val;
if (check(t[now].son[0],x1,y1,x2,y2)) res+=query(t[now].son[0],x1,y1,x2,y2,!R);
if (check(t[now].son[1],x1,y1,x2,y2)) res+=query(t[now].son[1],x1,y1,x2,y2,!R);
return res;
}
void ins(int now,int R) {
if (t[now].p[0]==t[tot].p[0]&&t[now].p[1]==t[tot].p[1]) {
t[now].val+=t[tot].val;
t[now].sum+=t[tot].val;
tot--; push_up(now);
return ;
}
int d=t[tot].p[R]>t[now].p[R];
if (!t[now].son[d]) t[now].son[d]=tot;
else ins(t[now].son[d],!R);
push_up(now);
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int root=0; read();
for (int lastans=0,cnt=0;;) {
int opt=read(); if (opt==3) break;
if (opt==1) {
int x=read()^lastans;
int y=read()^lastans;
int v=read()^lastans;
t[++tot]=(treeNode) {v,v,{0,0},{x,y},{x,y},{x,y}};
if (!root) {
root=tot;
push_up(tot);
} else ins(root,0);
} else {
int x1=read()^lastans;
int y1=read()^lastans;
int x2=read()^lastans;
int y2=read()^lastans;
printf("%d\n", lastans=query(root,x1,y1,x2,y2,0));
}
if (++cnt==60000) root=build(1,tot,0),cnt=0;
lastans=0;
}
return 0;
}