Moeebius @ 2022-09-11 12:01:27
RT,样例 AC,参考了第一篇题解的写法,但是有些细节和他不一样。
WA on #2 #3 #4 #5, 报错是读到了
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define mkp make_pair
#define pii pair<int,int>
#define lll __int128
#define ll long long
#define For(i,j,k) for(int i=(j); i<=(k); ++i)
#define ForDown(i,j,k) for(int i=(j); i>=(k); --i)
#define pb push_back
#define init(filename) freopen(filename ".in" ,"r",stdin);freopen(filename ".out" ,"w",stdout)
template<typename T>
il void read(T &x){ x=0;int f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;}
template<typename T, typename ... Args>
il void read(T &x, Args &... y){ read(x);read(y...); }
int n,lstAns=0,rt=0;
const int MAXN=2e5+5;
struct Node // 空间中的点
{
int pos[2],val;
Node(int x=0, int y=0, int w=0) : val(w) { pos[0]=x,pos[1]=y; }
}tmp[MAXN];
struct KDT // K-D Tree
{
int minv[2],maxv[2],sum,lc,rc,sz;
Node nd;
KDT()
{
memset(minv,0,sizeof(minv));
memset(minv,0,sizeof(maxv));
sum=lc=rc=sz=0;
nd=Node();
}
}T[MAXN];
il bool cmp1(const Node &x, const Node &y){ return x.pos[0]<y.pos[0]; }
il bool cmp2(const Node &x, const Node &y){ return x.pos[1]<y.pos[1]; }
int bac[MAXN],top=0,cnt=0;
il int newNd(){ return top?bac[top--]:++cnt; }
il void del(int p){ T[p]=KDT();bac[++top]=p; }
il void pushUp(int p) // 维护
{
int lc=T[p].lc,rc=T[p].rc;
For(i,0,1)
{
T[p].minv[i]=T[p].maxv[i]=T[p].nd.pos[i];
if(lc) T[p].minv[i]=min(T[p].minv[i],T[lc].minv[i]),T[p].maxv[i]=max(T[p].maxv[i],T[lc].maxv[i]);
if(rc) T[p].minv[i]=min(T[p].minv[i],T[rc].minv[i]),T[p].maxv[i]=max(T[p].maxv[i],T[rc].maxv[i]);
}
T[p].sum=T[p].nd.val+T[lc].sum+T[rc].sum;
T[p].sz=T[lc].sz+T[rc].sz+1;
}
void reinit(int p, int len) // 拍扁
{
if(T[p].lc) reinit(T[p].lc,len);
tmp[T[T[p].lc].sz+len+1]=T[p].nd,del(p);
if(T[p].rc) reinit(T[p].rc,T[T[p].lc].sz+len+1);
}
int rebuild(int l, int r, int d) // 重构
{
if(l>r) return 0;
int mid=(l+r)>>1,p=newNd();
nth_element(tmp+l,tmp+mid,tmp+r+1,d?cmp2:cmp1);
T[p].nd=tmp[mid];
T[p].lc=rebuild(l,mid-1,d^1), T[p].rc=rebuild(mid+1,r,d^1);
pushUp(p);
return p;
}
il void check(int &p, int d) // 判断是否重构
{
int lc=T[p].lc,rc=T[p].rc;
if(0.75*T[p].sz<1.0*T[lc].sz || 0.75*T[p].sz<1.0*T[rc].sz)
{
reinit(p,0);
p=rebuild(1,T[p].sz,d);
}
}
void insert(int &p, Node x, int d) // 加点
{
if(!p)
{
p=newNd();
T[p].nd=x;
pushUp(p);
return;
}
if(x.pos[d]<=T[p].nd.pos[d]) insert(T[p].lc,x,d^1);
else insert(T[p].rc,x,d^1);
pushUp(p);
check(p,d);
}
bool inRect(int xl, int xr, int yl, int yr, int XL, int XR, int YL, int YR) // 注意这里是判断小写字母的矩形是否在大写字母的矩形中
{
return xl>=XL && xr<=XR && yl>=YL && yr<=YR;
}
bool outRect(int xl, int xr, int yl, int yr, int XL, int XR, int YL, int YR)
{
return !inRect(xl,xr,yl,yr,XL,XR,YL,YR);
}
int query(int p, int xl, int xr, int yl, int yr) // 询问
{
if(!p || outRect(T[p].minv[0],T[p].maxv[0],T[p].minv[1],T[p].maxv[1],xl,xr,yl,yr)) return 0;
if(inRect(T[p].minv[0],T[p].maxv[0],T[p].minv[1],T[p].maxv[1],xl,xr,yl,yr)) return T[p].sum;
int ans=0;
if(inRect(T[p].nd.pos[0],T[p].nd.pos[0],T[p].nd.pos[1],T[p].nd.pos[1],xl,xr,yl,yr)) ans+=T[p].nd.val;
return query(T[p].lc,xl,xr,yl,yr)+query(T[p].rc,xl,xr,yl,yr)+ans;
}
signed main()
{
read(n);
int op;
while(scanf("%d",&op)==1)
{
if(op==3) break;
else if(op&1)
{
int x,y,a; read(x,y,a);
x^=lstAns,y^=lstAns,a^=lstAns;
insert(rt,Node(x,y,a),0);
}
else
{
int xl,xr,yl,yr;
read(xl,yl,xr,yr);
xl^=lstAns,xr^=lstAns,yl^=lstAns,yr^=lstAns;
lstAns=query(rt,xl,xr,yl,yr);
printf("%d\n", lstAns);
}
}
return 0;
}