BZOJ-4066: 简单题

[文章目录]

Description

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
1 x y A : 1<=x,y<=N,A是正整数,将格子x,y里的数字加上A
2 x1 y1 x2 y2: 1<=x1<= x2<=N 1<=y1<= y2<=N,输出x1 y1 x2 y2这个矩形内的数字和

KD-tree模板题。
对于二维平面上一个矩形区域,在KD-tree上只会有O(√n)个关键点与之对应。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline char nc()
{
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x)
{
    x=0; char f=0,ch=nc();
    while(!isdigit(ch)) {if(ch=='-') f=1; ch=nc();}
    while(isdigit(ch)) x=x*10+(ch^'0'),ch=nc();
    if(f) x=-x;
}
int n,d,rot,ans,cgg;
double arf=0.8;
struct KD_tree
{
    int p[2],mi[2],mx[2],ls,rs,w,sum,siz;
    void clear()
    {
        mi[0]=mx[0]=p[0];
        mi[1]=mx[1]=p[1];
        sum=w; siz=1;
        ls=rs=0;
    }
}t[201000];
bool operator < (KD_tree x,KD_tree y)
{
    return x.p[d]==y.p[d] ? x.p[d^1] < y.p[d^1] : x.p[d] < y.p[d];
}
void pushup(int p,int s)
{
    t[p].mi[0]=min(t[p].mi[0],t[s].mi[0]);
    t[p].mx[0]=max(t[p].mx[0],t[s].mx[0]);
    t[p].mi[1]=min(t[p].mi[1],t[s].mi[1]);
    t[p].mx[1]=max(t[p].mx[1],t[s].mx[1]);
    t[p].siz+=t[s].siz;
    t[p].sum+=t[s].sum;
}
int cg[201000];
bool cmp(int x,int y){return t[x]<t[y];}
void flatten(int x)
{
    if(!x) return ;
    flatten(t[x].ls);
    flatten(t[x].rs);
    cg[++cgg]=x; t[x].clear();
}
int build(int l,int r,int fl)
{
    int mid=(l+r)>>1; d=fl;
    nth_element(cg+l,cg+mid,cg+r+1,cmp);
    int re=cg[mid];
    if(l<mid) pushup(re,t[re].ls=build(l,mid-1,fl^1));
    if(r>mid) pushup(re,t[re].rs=build(mid+1,r,fl^1));
    return re;
}
void rebuild(int &x,int D)
{
    cgg=0; flatten(x);
    x=build(1,cgg,D);
}
void insert(int &p,int k,int fl,int D)
{
    if(!p) {p=k; return ;}
    pushup(p,k); d=D;
    if(t[k]<t[p])
    {
        if(!fl&&t[t[p].ls].siz+1>t[p].siz*arf) insert(t[p].ls,k,1,D^1),rebuild(p,D);
        else insert(t[p].ls,k,fl,D^1);
    }
    else
    {
        if(!fl&&t[t[p].rs].siz+1>t[p].siz*arf) insert(t[p].rs,k,1,D^1),rebuild(p,D);
        else insert(t[p].rs,k,fl,D^1);
    }
}
void query(int p,int x,int y,int dx,int dy)
{
    if(!p||dx<t[p].mi[0]||x>t[p].mx[0]||dy<t[p].mi[1]||y>t[p].mx[1]) return ;
    if(x<=t[p].mi[0]&&dx>=t[p].mx[0]&&y<=t[p].mi[1]&&dy>=t[p].mx[1])
    {
        ans+=t[p].sum;
        return ;
    }
    if(t[p].p[0]>=x&&t[p].p[0]<=dx&&t[p].p[1]>=y&&t[p].p[1]<=dy) ans+=t[p].w;
    query(t[p].ls,x,y,dx,dy);
    query(t[p].rs,x,y,dx,dy);
}
int main()
{
    int sw,x,y,dx,dy; read(sw);
    while(1)
    {
        read(sw);
        if(sw==3) break;
        if(sw==1)
        {
            ++n;
            read(t[n].p[0]); read(t[n].p[1]); read(t[n].w);
            t[n].p[0]^=ans; t[n].p[1]^=ans; t[n].w^=ans;
            t[n].clear(); insert(rot,n,0,0);
        }
        else
        {
            read(x); read(y); x^=ans; y^=ans;
            read(dx); read(dy); dx^=ans; dy^=ans;
            ans=0; query(rot,x,y,dx,dy);
            printf("%d\n",ans);
        }
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注