bzoj4066 简单题

来源:互联网 发布:360软件认证费用 编辑:程序博客网 时间:2024/06/05 07:53

【题意】

n*n网格,初始每个点权值为0,m个操作,共2种:

1.(x,y)点权+z

2.查询矩形(x1,y1)(x2,y2)的点权和

强制在线

【数据范围】

n<=500000,m<=200000

【思路】

kd-tree模板题,注意kd-tree需定期重构。

矩形求和的计算方法:

若某点子树边框包含于查询矩形,则直接更新答案。

若某点子树边框与查询矩形不相交,则忽略该子树。

【时间复杂度】

O(m*sqrt(m))

#include<cstdio>#include<cstring>#include<algorithm>#define N 200010using namespace std; struct aa{int d[2], x;}a[N];struct tt{int l, r, mx[2], mn[2], d[2], x, sum;}t[N];int n, m, l, temp, lastans, D, B, x1, x2, y1, y2; inline int read(){    int x=0, f=1; char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}    return x*f;} bool operator<(aa a, aa b){return a.d[D]<b.d[D];} void update(int i){    t[i].sum=t[t[i].l].sum+t[t[i].r].sum+t[i].x;    for(int j=0; j<=1; j++){        t[i].mx[j]=t[i].mn[j]=t[i].d[j];        if(t[i].l){            t[i].mx[j]=max(t[i].mx[j], t[t[i].l].mx[j]);            t[i].mn[j]=min(t[i].mn[j], t[t[i].l].mn[j]);        }        if(t[i].r){            t[i].mx[j]=max(t[i].mx[j], t[t[i].r].mx[j]);            t[i].mn[j]=min(t[i].mn[j], t[t[i].r].mn[j]);        }    }} void kd_maketree(int L, int R, int now){    t[l].l=t[l].r=0;    D=now; int mid=(L+R)>>1;    nth_element(a+L, a+mid, a+R+1);    t[l].d[0]=a[mid].d[0]; t[l].d[1]=a[mid].d[1]; t[l].x=a[mid].x;    int l1=l;    if(L<mid){l++; t[l1].l=l; kd_maketree(L, mid-1, now^1);}    if(mid<R){l++; t[l1].r=l; kd_maketree(mid+1, R, now^1);}    update(l1);} void kd_ins(int i, int x, int y, int z, int now, int fa, int p){    if(!i){        t[++l].d[0]=x; t[l].d[1]=y; t[l].x=z; update(l);        if(!p)t[fa].l=l; else t[fa].r=l;        return;    }    if(t[i].d[0]==x&&t[i].d[1]==y){t[i].x+=z; t[i].sum+=z; return;}    if(!now){        if(x<=t[i].d[0])kd_ins(t[i].l, x, y, z, now^1, i, 0);        else kd_ins(t[i].r, x, y, z, now^1, i, 1);    }else{        if(y<=t[i].d[1])kd_ins(t[i].l, x, y, z, now^1, i, 0);        else kd_ins(t[i].r, x, y, z, now^1, i, 1);    }    update(i);} int in(int X1, int X2, int Y1, int Y2){    if(x1<=X1&&X2<=x2&&y1<=Y1&&Y2<=y2)return 1;    return 0;}int out(int X1, int X2, int Y1, int Y2){    if(X2<x1||x2<X1||Y2<y1||y2<Y1)return 1;    return 0;}void check(int i){    if(!i)return;    if(in(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1])){lastans+=t[i].sum; return;}    if(out(t[i].mn[0], t[i].mx[0], t[i].mn[1], t[i].mx[1]))return;    if(in(t[i].d[0], t[i].d[0], t[i].d[1], t[i].d[1]))lastans+=t[i].x;    check(t[i].l); check(t[i].r);} int main(){    m=read(); lastans=0;    l=n=0; B=10000; temp=read();    while(temp<3){        if(temp==1){            n++; a[n].d[0]=read()^lastans; a[n].d[1]=read()^lastans; a[n].x=read()^lastans;            if(!l){                l++; t[l].l=t[l].r=0;                t[l].d[0]=a[n].d[0]; t[l].d[1]=a[n].d[1]; t[l].x=a[n].x;                update(l);            }else kd_ins(1, a[n].d[0], a[n].d[1], a[n].x, 0, 0, 0);            if(n==B){                l=1; kd_maketree(1, n, 0);                B+=10000;            }        }else{            x1=read()^lastans; y1=read()^lastans; x2=read()^lastans; y2=read()^lastans;            lastans=0; check(1); printf("%d\n", lastans);        }        temp=read();    }    return 0;}


0 0
原创粉丝点击