bzoj4066 简单题

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这个矩形内的数字和

3

终止程序

 

Input

输入文件第一行一个正整数N。
接下来每行一个操作。每条命令除第一个数字之外,
均要异或上一次输出的答案last_ans,初始时last_ans=0。

Output

对于每个2操作,输出一个对应的答案。

k-d树维护插入和查询,每插入一定次数重构整棵树

#include<cstdio>
#include<algorithm>
int X[2],A,la=0;
int mns[2],mxs[2],x0,x1,y0,y1;
inline void mins(int&x,int y){if(x>y)x=y;}
inline void maxs(int&x,int y){if(x<y)x=y;}
int read(){
    int x=0,c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return x;
}
struct node{
    int m[2];
    int mn[2],mx[2];
    int v,s,c[2];
    void set(){
        for(int i=0;i<2;i++)m[i]=mn[i]=mx[i]=X[i];
        v=s=A;
        c[0]=c[1]=0;
    }
};
struct pos{
    int x,y,v;
};
int d_x=0;
bool operator<(pos a,pos b){
    if(d_x)return a.y<b.y;
    else return a.x<b.x;
}
int op;
node ns[200005];
pos ps[200005];
int np=1,pp=0;
void upd(int ww){
    node&w=ns[ww];
    w.s=w.v;
    for(int i=0;i<2;i++){
        if(w.c[i]){
            node&u=ns[w.c[i]];
            w.s+=u.s;
            for(int j=0;j<2;j++)
                mins(w.mn[j],u.mn[j]),
                maxs(w.mx[j],u.mx[j]);
        }
    }
}
void insert(int ww,int dx){
    node&w=ns[ww];
    bool f=X[dx]<w.m[dx];
    if(w.c[f])insert(w.c[f],dx^1);
    else w.c[f]=np++;
    upd(ww);
}
void ins(){
    if(np>1)insert(1,0);
    else np++;
}
int build(int l,int r,int d){
    d_x=d;
    int m=l+r>>1;
    std::nth_element(ps+l,ps+m,ps+r);
    int ww=np++;
    node&w=ns[ww];
    X[0]=ps[m].x,X[1]=ps[m].y,A=ps[m].v;
    w.set();
    if(l<m)w.c[0]=build(l,m,d^1);
    else w.c[0]=0;
    if(m+1<r)w.c[1]=build(m+1,r,d^1);
    else w.c[1]=0;
    upd(ww);
    return ww;
}
void rebuild(){
    np=1;
    build(0,pp,0);
}
int ask(int ww=1){
    if(!ww)return 0;
    node&w=ns[ww];
    if(x0<=w.mn[0]&&w.mx[0]<=x1&&y0<=w.mn[1]&&w.mx[1]<=y1)return w.s;
    if(x0>w.mx[0]||x1<w.mn[0]||y0>w.mx[1]||y1<w.mn[1])return 0;
    int a=0;
    if(x0<=w.m[0]&&w.m[0]<=x1&&y0<=w.m[1]&&w.m[1]<=y1)a=w.v;
    for(int i=0;i<2;i++)a+=ask(w.c[i]);
    return a;
}
int t=0;
int main(){
    read();
    while(1){
        op=read();
        if(op==3)break;
        if(op==1){
            ps[pp].x=X[0]=read()^la;
            ps[pp].y=X[1]=read()^la;
            ps[pp++].v=A=read()^la;
            ns[np].set();
            ins();
            t++;
            if(t>10000)rebuild(),t=0;
        }else{
            x0=mns[0]=read()^la;
            y0=mns[1]=read()^la;
            x1=mxs[0]=read()^la;
            y1=mxs[1]=read()^la;
            printf("%d
",la=ask());
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ccz181078/p/5148169.html