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操作,输出一个对应的答案。

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范围内并且解码之后数据仍合法。

样例解释见OJ2683

新加数据一组,但未重测—-2015.05.24

 

我终于过了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

由于内存很紧,我们不能用树套树来做,但k-d树还是可以的。

考虑出题人可能将k-d树的形态搞得很糟糕,我们可以定期重建整棵树

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=200010;
int n,D,lastans;
struct Point {
    int d[2],mx[2],mn[2],v,l,r,sum;
    bool operator == (const Point& ths) const {return d[0]==ths.d[0]&&d[1]==ths.d[1];}
    bool operator < (const Point& ths) const {return d[D]<ths.d[D];}
}p[maxn];
int 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;}
int 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;}
struct Kd_Tree {
    Point t[maxn],now;
    int rt,cnt;
    Kd_Tree() {t[0].mn[0]=t[0].mn[1]=2e9;t[0].mx[0]=t[0].mx[1]=-2e9;}
    void maintain(int k) {
        int l=t[k].l,r=t[k].r;
        rep(0,1) t[k].mn[i]=min(t[k].d[i],min(t[l].mn[i],t[r].mn[i])),t[k].mx[i]=max(t[k].d[i],max(t[l].mx[i],t[r].mx[i]));
        t[k].sum=t[l].sum+t[r].sum+t[k].v;
    }
    void insert(int& k,int d) {
        if(!k) k=++cnt,t[k].d[0]=t[k].mx[0]=t[k].mn[0]=now.d[0],t[k].d[1]=t[k].mx[1]=t[k].mn[1]=now.d[1];
        if(now==t[k]) {
            t[k].v+=now.v;t[k].sum+=now.v;
            return;
        }
        if(now.d[d]<t[k].d[d]) insert(t[k].l,d^1);
        else insert(t[k].r,d^1);
        maintain(k);
    }
    int query(int k,int x1,int y1,int x2,int y2) {
        if(!k) return 0;
        if(in(x1,y1,x2,y2,t[k].mn[0],t[k].mn[1],t[k].mx[0],t[k].mx[1])) return t[k].sum;
        if(out(x1,y1,x2,y2,t[k].mn[0],t[k].mn[1],t[k].mx[0],t[k].mx[1])) return 0;
        int ret=0;
        if(in(x1,y1,x2,y2,t[k].d[0],t[k].d[1],t[k].d[0],t[k].d[1])) ret+=t[k].v;
        ret+=query(t[k].l,x1,y1,x2,y2)+query(t[k].r,x1,y1,x2,y2);
        return ret;
    }
    int build(int l,int r,int d) {
        if(l>r) return 0;
        int mid=l+r>>1;D=d;nth_element(p+l,p+mid,p+r+1);
        t[mid]=p[mid];t[mid].l=build(l,mid-1,d^1);t[mid].r=build(mid+1,r,d^1);
        maintain(mid);return mid;
    }
}T;
int main() {
    n=read();int ToT=0;
    while(1) {
        int tp=read();
        if(tp==3) break;
        else if(tp==1) {
            int x=read()^lastans,y=read()^lastans;
            T.now.d[0]=x;T.now.d[1]=y;
            T.now.v=T.now.sum=read()^lastans;
            T.insert(T.rt,0);
            if(++ToT==7000) {
                rep(1,T.cnt) p[i]=T.t[i];
                T.rt=T.build(1,T.cnt,0);ToT=0;
            }
        }
        else {
            int x=read()^lastans,y=read()^lastans,x2=read()^lastans,y2=read()^lastans;
            printf("%d\n",lastans=T.query(T.rt,x,y,x2,y2));
        }
    }
    return 0;
}
View Code

 

posted @ 2015-07-04 10:24  wzj_is_a_juruo  阅读(181)  评论(0编辑  收藏  举报