1. 程式人生 > >[BZOJ 4066]簡單題

[BZOJ 4066]簡單題

+= pac () upd body r+ odi main void

Description
你有一個N*N的棋盤,每個格子內有一個整數,初始時的時候全部為0,現在需要維護兩種操作:

命令 參數限制 內容
\(1\,x\,y\,A\) \(1\leqslant x,y\leqslant N\)\(A\)是正整數 將格子\(x,y\)裏的數字加上\(A\)
\(2\,x_1\,y_1\,x_2\,y_2\) \(1\leqslant x_1\leqslant x_2\leqslant N\\1\leqslant y_1\leqslant y_2\leqslant N\) 輸出\(x_1\,y_1\,x_2\,y_2\)這個矩形內的數字和
\(3\)
終止程序

Input
輸入文件第一行一個正整數N。
接下來每行一個操作。每條命令除第一個數字之外,
均要異或上一次輸出的答案last_ans,初始時last_ans=0。

Output
對於每個2操作,輸出一個對應的答案。

Sample Input
4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3

Sample Output
3
5

HINT
\(1\leqslant N\leqslant500000\),操作數不超過200000個,內存限制20M,保證答案在int範圍內並且解碼之後數據仍合法。

20M顯然不能樹套樹……於是我們用一個簡單的數據結構——KD-Tree

自信的寫了一發,交上去TLE……一測數據發現極限數據跑了2m……

完全不會優化啊……還是%%%hzwer

定一個閥值,當KD-Tree插入操作達到這個閥值時,就暴力重構KD-Tree

然後就可以過了……

/*program from Wolfycz*/
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
    int x=0,f=1; char ch=gc();
    for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline int read(){
    int x=0,f=1; char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<3)+(x<<1)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x<0)    putchar('-'),x=-x;
    if (x>9)    print(x/10);
    putchar(x%10+'0');
}
const int N=2e5,V=1e4;
int T;
struct S1{
    #define ls(p) tree[p].ls
    #define rs(p) tree[p].rs
    struct node{
        int v[2],Max[2],Min[2];
        int ls,rs,type,val,sum;
        void insert(int type,int val){v[type]=Min[type]=Max[type]=val;}
        bool operator <(const node &tis)const{return v[T]<tis.v[T];}
    }tree[N+10];
    int root,tot;
    int L[2],R[2];
    void Add(int *a,int v){a[0]=a[1]=v;}
    void init(){Add(tree[0].Max,-inf),Add(tree[0].Min,inf);}
    void updata(int p){
        tree[p].Min[0]=min(tree[p].v[0],min(tree[ls(p)].Min[0],tree[rs(p)].Min[0]));
        tree[p].Min[1]=min(tree[p].v[1],min(tree[ls(p)].Min[1],tree[rs(p)].Min[1]));
        tree[p].Max[0]=max(tree[p].v[0],max(tree[ls(p)].Max[0],tree[rs(p)].Max[0]));
        tree[p].Max[1]=max(tree[p].v[1],max(tree[ls(p)].Max[1],tree[rs(p)].Max[1]));
    }
    int rebuild(int l,int r,int type){
        T=type;
        int mid=(l+r)>>1,p=mid;
        nth_element(tree+l,tree+mid,tree+r+1);
        tree[p].type=type,tree[p].sum=0;
        tree[p].ls=tree[p].rs=0;
        if (l<mid)  ls(p)=rebuild(l,mid-1,type^1);
        if (r>mid)  rs(p)=rebuild(mid+1,r,type^1);
        updata(p);
        tree[p].sum=tree[ls(p)].sum+tree[rs(p)].sum+tree[p].val;
        return p;
    }
    void Modify(int &p,int x,int y,int v){
        if (!p){
            p=++tot;
            tree[p].insert(0,x);
            tree[p].insert(1,y);
            tree[p].type=rand()&1;
            tree[p].val=tree[p].sum=v;
            return;
        }
        (tree[p].type?y:x)<tree[p].v[tree[p].type]?Modify(ls(p),x,y,v):Modify(rs(p),x,y,v);
        updata(p),tree[p].sum=tree[ls(p)].sum+tree[p].val+tree[rs(p)].sum;
    }
    int Query(int p){
        if (L[0] >tree[p].Max[0]||R[0] <tree[p].Min[0]||L[1] >tree[p].Max[1]||R[1] <tree[p].Min[1]) return 0;
        if (L[0]<=tree[p].Min[0]&&tree[p].Max[0]<=R[0]&&L[1]<=tree[p].Min[1]&&tree[p].Max[1]<=R[1]) return tree[p].sum;
        int res=0;
        if (L[0]<=tree[p].v[0]&&tree[p].v[0]<=R[0]&&L[1]<=tree[p].v[1]&&tree[p].v[1]<=R[1]) res=tree[p].val;
        res+=Query(ls(p))+Query(rs(p));
        return res;
    }
    int Query(int x1,int y1,int x2,int y2){
        L[0]=x1,R[0]=x2,L[1]=y1,R[1]=y2;
        return Query(root);
    }
}KDT;//KD-Tree
int main(){
    srand(time(0));
    int n=read(),cnt=0;
    KDT.init();
    for (int lastans=0;;){
        int type=read();
        if (type==1){
            cnt++;
            int x=read()^lastans,y=read()^lastans,v=read()^lastans;
            KDT.Modify(KDT.root,x,y,v);
            if (cnt%V==0)   KDT.root=KDT.rebuild(1,KDT.tot,0);
        }
        if (type==2){
            int x1=read()^lastans,y1=read()^lastans,x2=read()^lastans,y2=read()^lastans;
            printf("%d\n",lastans=KDT.Query(x1,y1,x2,y2));
        }
        if (type==3)    break;
    }
    return 0;
}

[BZOJ 4066]簡單題