萌新求助 KDT 简单题

P4148 简单题

Moeebius @ 2022-09-11 12:01:27

RT,样例 AC,参考了第一篇题解的写法,但是有些细节和他不一样。

WA on #2 #3 #4 #5, 报错是读到了 0

#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;
}

|