[bzoj4066]簡單題

4066: 簡單題

Time Limit: 50 Sec Memory Limit: 20 MB
Submit: 1563 Solved: 420
[Submit][Status][Discuss]
Description

這裏寫圖片描述

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<=N<=500000,操作數不超過200000個,內存限制20M,保證答案在int範圍內並且解碼之後數據仍合法。

KD樹模板題。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=200010;
int n,ans,siz,root,o,D;
struct S{
    int v,sum,d[2],minn[2],maxn[2],l,r;
    int &operator [](int x){
        return d[x];
    }
    bool operator == (const S &x)const{
        return x.d[0]==d[0]&&x.d[1]==d[1];
    }

    bool operator < (const S &x)const{
        return d[D]<x.d[D];
    }
}tr[N],p[N],now;
inline int IN(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;
}
inline void update(int k){
    int l=tr[k].l,r=tr[k].r,i;
    tr[k].sum=tr[k].v+tr[l].sum+tr[r].sum;
    for(i=0;i<=1;++i){
        tr[k].minn[i]=tr[k].maxn[i]=tr[k][i];
        if(l){
            tr[k].minn[i]=min(tr[k].minn[i],tr[l].minn[i]);
            tr[k].maxn[i]=max(tr[k].maxn[i],tr[l].maxn[i]); 
        }
        if(r){
            tr[k].minn[i]=min(tr[k].minn[i],tr[r].minn[i]);
            tr[k].maxn[i]=max(tr[k].maxn[i],tr[r].maxn[i]); 
        }
    }
}
inline void insert(int &k,int flag){
    if(!k){
        k=++siz;
        tr[k][0]=tr[k].minn[0]=tr[k].maxn[0]=now[0];
        tr[k][1]=tr[k].minn[1]=tr[k].maxn[1]=now[1];
    }
    if(now==tr[k]){
        tr[k].sum+=now.sum;
        tr[k].v+=now.v;
        return ;    
    }
    if(now[flag]<tr[k][flag]) insert(tr[k].l,flag^1);
    else insert(tr[k].r,flag^1);
    update(k); 
}
#define mid (l+r)/2
inline int rebuild(int l,int r,int flag){
    if(l>r) return 0;
    D=flag;nth_element(p+l,p+mid,p+r+1);
    tr[mid]=p[mid];
    tr[mid].l=rebuild(l,mid-1,flag^1);
    tr[mid].r=rebuild(mid+1,r,flag^1);
    update(mid);
    return mid;
}
inline bool in(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){
    return x1<=X1&&x2>=X2&&y1<=Y1&&y2>=Y2;
}
inline bool out(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){
    return x1>X2||x2<X1||y1>Y2||y2<Y1;
}
inline int query(int k,int x,int y,int xx,int yy){
    if(!k) return 0;
    int sum=0;
    if(in(x,y,xx,yy,tr[k].minn[0],tr[k].minn[1],tr[k].maxn[0],tr[k].maxn[1])) return tr[k].sum;
    if(out(x,y,xx,yy,tr[k].minn[0],tr[k].minn[1],tr[k].maxn[0],tr[k].maxn[1])) return 0;
    if(in(x,y,xx,yy,tr[k][0],tr[k][1],tr[k][0],tr[k][1])) sum+=tr[k].v;
    return sum+query(tr[k].l,x,y,xx,yy)+query(tr[k].r,x,y,xx,yy);
}
int main(){
    int i,t,x,y,xx,yy,z;
    n=IN();
    o=10000;
    while(1){
        t=IN();
        if(t==3) break;
        x=IN();y=IN();
        x^=ans;y^=ans;
        if(t==1){
            z=IN();z^=ans;
            now[0]=x;now[1]=y;
            now.v=now.sum=z;
            insert(root,0);
            if(siz==o){
                for(i=1;i<=siz;++i) p[i]=tr[i];
                root=rebuild(1,siz,0);
                o+=10000;
            }
        }
        if(t==2){
            xx=IN();yy=IN();
            xx^=ans;yy^=ans;
            ans=query(root,x,y,xx,yy);
            printf("%d\n",ans);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章