话说本来想写替罪羊重构,可是后来发现狂T不止。
其实还有一个思路是,动态维护kdtree,每次插入log 个节点,坐标完全是实际坐标,需要n log n的空间,本题卡空间
/**************************************************************
Problem: 4066
User: zhhx
Language: C++
Result: Accepted
Time:49076 ms
Memory:12468 kb
****************************************************************/
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
inline int read()
{
int ans,f=1;char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans*f;
}
int D;
int n,m,ans,val;
int num;
struct aaa
{
int d[2],val;
}tmp[200005];
struct aa
{
int mi[2],mx[2],d[2];
int sum,size,val;
int lc,rc;
}a[200005];
void up(int u,int v)
{
for (int i=0;i<=1;i++)
{
a[u].mi[i]=min(a[u].mi[i],a[v].mi[i]);
a[u].mx[i]=max(a[u].mx[i],a[v].mx[i]);
}
a[u].size=a[a[u].lc].size+a[a[u].rc].size+1;
a[u].sum=a[a[u].lc].sum+a[a[u].rc].sum+a[u].val;
}
stack<int> s;
int uu,fa,rt;
int new_node()
{
int u;
if (s.empty()) return u=++n;
else u=s.top(),s.pop();
return u;
}
void insert(int &u,int d[2],int dd)
{
if (u==0)
{
u=new_node();
a[u].mi[0]=a[u].mx[0]=a[u].d[0]=d[0];
a[u].mi[1]=a[u].mx[1]=a[u].d[1]=d[1];
a[u].sum=a[u].val=val;a[u].size=1;a[u].lc=a[u].rc=0;
return;
}
if (a[u].d[0]==d[0]&&a[u].d[1]==d[1])
{
a[u].sum+=val,a[u].val+=val;
return ;
}
if (a[u].d[dd]>d[dd]) {insert(a[u].lc,d,dd^1),up(u,a[u].lc);if (a[u].lc==uu) fa=u;}
else {insert(a[u].rc,d,dd^1),up(u,a[u].rc);if (a[u].rc==uu) fa=u;}
int mx=max(a[a[u].lc].size,a[a[u].rc].size);
if (mx>0.63*a[u].size&&a[u].size>10000) uu=u;
}
bool in(int x,int y,int xx,int yy,int d1[2],int d2[2])
{
if (d1[0]<=x&&d1[1]<=y&&d2[0]>=xx&&d2[1]>=yy) return true;return false;
}
bool out(int x,int y,int xx,int yy,int d1[2],int d2[2])
{
if (d2[0]<x||d2[1]<y||d1[0]>xx||d1[1]>yy) return true;return false;
}
int query(int u,int d1[2],int d2[2])
{
if (u==0) return 0;
if (out(a[u].mi[0],a[u].mi[1],a[u].mx[0],a[u].mx[1],d1,d2)) return 0;
if (in(a[u].mi[0],a[u].mi[1],a[u].mx[0],a[u].mx[1],d1,d2)) return a[u].sum;
int ans=0;
if (in(a[u].d[0],a[u].d[1],a[u].d[0],a[u].d[1],d1,d2)) ans+=a[u].val;//注意当前节点本身的值,这里wa了好几次
ans+=query(a[u].lc,d1,d2)+query(a[u].rc,d1,d2);
return ans;
}
void dfs(int u)
{
if (u==0) return ;
s.push(u);
num++;
tmp[num].d[0]=a[u].d[0];
tmp[num].d[1]=a[u].d[1];
tmp[num].val=a[u].val;
dfs(a[u].lc);dfs(a[u].rc);
}
bool cmp(aaa a,aaa b)
{
return a.d[D]<b.d[D]||(a.d[0]==b.d[0]&&a.d[1]<b.d[1]);
}
int build(int l,int r,int dd)
{
int mid=(l+r)>>1;
D=dd;
nth_element(tmp+l,tmp+mid,tmp+r+1,cmp);
int u=new_node();
a[u].mi[0]=a[u].mx[0]=a[u].d[0]=tmp[mid].d[0];
a[u].mi[1]=a[u].mx[1]=a[u].d[1]=tmp[mid].d[1];
a[u].size=1;a[u].val=a[u].sum=tmp[mid].val;
if (l<mid) a[u].lc=build(l,mid-1,dd^1),up(u,a[u].lc);else a[u].lc=0;
if (mid<r) a[u].rc=build(mid+1,r,dd^1),up(u,a[u].rc);else a[u].rc=0;
return u;
}
void rebuild(int u)
{
num=0;
dfs(u);
int tt=build(1,num,0);
if (fa==0) {rt=tt;return;}
if (a[fa].lc==u) a[fa].lc=tt;
else a[fa].rc=tt;
}
int main()
{
int nn=read();
int op,d1[2],d2[2];
while (true)
{
op=read();
if (op==3) break;
if (op==1)
{
d1[0]=read()^ans,d1[1]=read()^ans,val=read()^ans;
fa=uu=0;
insert(rt,d1,0);
if (rt==uu) fa=0;
if (uu>0) rebuild(uu);
}
else
{
d1[0]=read()^ans,d1[1]=read()^ans,d2[0]=read()^ans,d2[1]=read()^ans;
ans=query(rt,d1,d2);
printf("%d\n",ans);
}
}
return 0;
}