[BZOJ4066]简单题(kd-tree)

来源:互联网 发布:网络谣言的危害 编辑:程序博客网 时间:2024/06/12 19:34

题目描述

传送门

题解

有强制在线,不能用cdq分治做了= =
不过可以用kd-tree
由于是要求和,维护一个sum
如果要是左右子树都在范围内,直接加和
如果都不在范围内,跳过
否则递归子树

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 200005int s,opt,n,x,y,v,p,q,cmpd,root,ans;struct data{    int l,r,val,sum;    int d[2],mx[2],mn[2];}tr[N];void update(int x){    int l=tr[x].l,r=tr[x].r;    tr[x].sum=tr[x].val;    if (l)    {        tr[x].mn[0]=min(tr[x].mn[0],tr[l].mn[0]);        tr[x].mx[0]=max(tr[x].mx[0],tr[l].mx[0]);        tr[x].mn[1]=min(tr[x].mn[1],tr[l].mn[1]);        tr[x].mx[1]=max(tr[x].mx[1],tr[l].mx[1]);        tr[x].sum+=tr[l].sum;    }    if (r)    {        tr[x].mn[0]=min(tr[x].mn[0],tr[r].mn[0]);        tr[x].mx[0]=max(tr[x].mx[0],tr[r].mx[0]);        tr[x].mn[1]=min(tr[x].mn[1],tr[r].mn[1]);        tr[x].mx[1]=max(tr[x].mx[1],tr[r].mx[1]);        tr[x].sum+=tr[r].sum;    }}int cmp(data a,data b){    return a.d[cmpd]<b.d[cmpd]||a.d[cmpd]==b.d[cmpd]&&a.d[cmpd^1]<b.d[cmpd^1];}int rebuild(int l,int r,int d){    int mid=(l+r)>>1;    cmpd=d;    nth_element(tr+l,tr+mid,tr+r+1,cmp);    tr[mid].mx[0]=tr[mid].mn[0]=tr[mid].d[0];    tr[mid].mx[1]=tr[mid].mn[1]=tr[mid].d[1];    tr[mid].sum=tr[mid].val;    tr[mid].l=tr[mid].r=0;    if (l<mid) tr[mid].l=rebuild(l,mid-1,d^1);    if (mid<r) tr[mid].r=rebuild(mid+1,r,d^1);    update(mid);    return mid;}void insert(int x){    if (!root)    {        root=x;        return;    }    int now=root,d=0;    while (1)    {        tr[now].mn[0]=min(tr[now].mn[0],tr[x].mn[0]);        tr[now].mx[0]=max(tr[now].mx[0],tr[x].mx[0]);        tr[now].mn[1]=min(tr[now].mn[1],tr[x].mn[1]);        tr[now].mx[1]=max(tr[now].mx[1],tr[x].mx[1]);        tr[now].sum+=tr[x].sum;        if (tr[x].d[d]<=tr[now].d[d])        {            if (tr[now].l) now=tr[now].l;            else {tr[now].l=x;break;}        }        else        {            if (tr[now].r) now=tr[now].r;            else {tr[now].r=x;break;}        }        d^=1;    }}bool ok(int id){    return (tr[id].d[0]>=x&&tr[id].d[0]<=p&&tr[id].d[1]>=y&&tr[id].d[1]<=q);}int check(int id){    if (tr[id].mn[0]>=x&&tr[id].mx[0]<=p&&tr[id].mn[1]>=y&&tr[id].mx[1]<=q) return 1;    else if (tr[id].mx[0]<x||tr[id].mn[0]>p||tr[id].mx[1]<y||tr[id].mn[1]>q) return -1;    else return 0;}void query(int now){    if (ok(now)) ans+=tr[now].val;    if (tr[now].l)    {        int t=check(tr[now].l);        if (t==1) ans+=tr[tr[now].l].sum;        else if (t==0) query(tr[now].l);    }    if (tr[now].r)    {        int t=check(tr[now].r);        if (t==1) ans+=tr[tr[now].r].sum;        else if (t==0) query(tr[now].r);    }}int main(){    scanf("%d",&s);    while (~scanf("%d",&opt))    {        if (opt==3) break;        if (opt==1)        {            scanf("%d%d%d",&x,&y,&v);++n;            x^=ans,y^=ans,v^=ans;            tr[n].mx[0]=tr[n].mn[0]=tr[n].d[0]=x;            tr[n].mx[1]=tr[n].mn[1]=tr[n].d[1]=y;            tr[n].val=tr[n].sum=v;            insert(n);            if (n%10000==0) root=rebuild(1,n,0);        }        else        {            scanf("%d%d%d%d",&x,&y,&p,&q);            x^=ans,y^=ans,p^=ans,q^=ans;            ans=0;            query(root);            printf("%d\n",ans);        }    }    return 0;}
0 0
原创粉丝点击