50s卡过..不知道为什么这么慢
kdt模板题
格子(x,y)里的加A可以直接插入一个值为A的点(x,y),如果原来有这个点了也没关系
因为插入可能导致树不平衡,所以用替罪羊树的重构思想,不满足平衡条件时暴力重构子树
2017.12.29 upd: 感谢学弟的指正代码重构部分写错了,带进去的那个D不一定是0,改了之后真的快了挺多的qwq….
code:
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 510000;
const int maxm = 200100;
const int maxd = 2;
const double A = 0.74;
inline int read()
{
char c; int x;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
return x;
}
inline void up(int &x,const int &y){if(x<y)x=y;}
inline void down(int &x,const int &y){if(x>y)x=y;}
struct KD_tree
{
int pos[maxd],u[maxd],d[maxd];
int c,s,siz,l,r,nowd;
}kd[maxm]; int root,tot;
int cmp_d;
inline bool cmp(const int &x,const int &y){return kd[x].pos[cmp_d]<kd[y].pos[cmp_d];}
int id[maxm],cnt;
inline void push_up(KD_tree &X)
{
int lc=X.l,rc=X.r;
if(lc)
{
up(X.u[0],kd[lc].u[0]);
up(X.u[1],kd[lc].u[1]);
down(X.d[0],kd[lc].d[0]);
down(X.d[1],kd[lc].d[1]);
X.c+=kd[lc].c;
X.siz+=kd[lc].siz;
}
if(rc)
{
up(X.u[0],kd[rc].u[0]);
up(X.u[1],kd[rc].u[1]);
down(X.d[0],kd[rc].d[0]);
down(X.d[1],kd[rc].d[1]);
X.c+=kd[rc].c;
X.siz+=kd[rc].siz;
}
}
void dfs(int &x)
{
if(kd[x].l) dfs(kd[x].l);
id[++cnt]=x;
if(kd[x].r) dfs(kd[x].r);
x=0;
}
int build(const int &l,const int &r,int D)
{
int mid=(l+r)>>1;
cmp_d=D; nth_element(id+l,id+mid,id+r+1,cmp);
int x=id[mid];
KD_tree &X=kd[x];
X.d[0]=X.u[0]=X.pos[0]; X.d[1]=X.u[1]=X.pos[1];
X.c=X.s; X.siz=1; X.nowd=D;
if(l!=mid) X.l=build(l,mid-1,!D);
if(mid!=r) X.r=build(mid+1,r,!D);
push_up(kd[x]);
return x;
}
inline void rebuild(int &x)
{
cnt=0; int nowd=kd[x].nowd;
int tx=x; dfs(tx); x=build(1,cnt,nowd);
}
int *tmp,kt;
int pos[maxd];
void ins(int &x,const int &c,int D)
{
if(!x)
{
KD_tree &t=kd[x=++tot];
t.pos[0]=t.u[0]=t.d[0]=pos[0];
t.pos[1]=t.u[1]=t.d[1]=pos[1];
t.c=c; t.s=c; t.siz=1;
t.nowd=D;
tmp=&kt;
return ;
}
KD_tree &t=kd[x];
t.c+=c; t.siz++;
up(t.u[0],pos[0]); up(t.u[1],pos[1]);
down(t.d[0],pos[0]); down(t.d[1],pos[1]);
if(pos[D]<=t.pos[D]) ins(t.l,c,!D);
else ins(t.r,c,!D);
if(kd[t.l].siz>t.siz*A||kd[t.r].siz>t.siz*A)
tmp=&x;
}
int Ans;
int Pd[maxd],Pu[maxd];
void Query(const int &x)
{
KD_tree &X=kd[x];
if(X.d[0]>=Pd[0]&&X.d[1]>=Pd[1]&&X.u[0]<=Pu[0]&&X.u[1]<=Pu[1]) {Ans+=X.c; return;}
if(X.u[0]<Pd[0]||X.u[1]<Pd[1]||X.d[0]>Pu[0]||X.d[1]>Pu[1]) return;
if(X.pos[0]>=Pd[0]&&X.pos[1]>=Pd[1]&&X.pos[0]<=Pu[0]&&X.pos[1]<=Pu[1])
Ans+=X.s;
Query(X.l);
Query(X.r);
}
int main()
{
//freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);
int n=read(); Ans=0;
while(1)
{
int temp=read();
if(temp==3) break;
if(temp==1)
{
pos[0]=read()^Ans,pos[1]=read()^Ans;
int c=read(); c^=Ans;
ins(root,c,0);
if((*tmp)) rebuild((*tmp));
}
else
{
Pd[0]=read()^Ans,Pd[1]=read()^Ans;
Pu[0]=read()^Ans,Pu[1]=read()^Ans;
Ans=0; Query(root);
printf("%d\n",Ans);
}
}
return 0;
}