4154: [Ipsc2015]Generating Synergy K-D tree

来源:互联网 发布:淘宝建设合同范本 编辑:程序博客网 时间:2024/06/15 22:16

按照dfs序建K-D树,用deepi表示i在原树中的深度,想想成二维平面中的点,第一维是dfs序,第二维是深度,则对于一个染色操作其实就是在二维平面内的区域[inx..outx][deepx..deepx+l]内进行覆盖,可以用K-D树来解决。
sb错误get。。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define inf 1e9#define N 100005#define ll long long #define mod 1000000007using namespace std;int n,c,q,a,l,x1,x2,y1,y2,D,dfn,cnt,ans,root;struct node {    int d[2],mn[2],mx[2];    int tag,col,fa;};node tree[N];int ls[N],rs[N];int head[N],deep[N],next[N],list[N],in[N],out[N],id[N],stack[N];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x,int y){    next[++cnt]=head[x];    head[x]=cnt;    list[cnt]=y;}inline bool operator<(node a,node b){    return a.d[D]<b.d[D];}void dfs(int x){    in[x]=++dfn;     tree[x].d[0]=dfn; tree[x].d[1]=deep[x]; tree[x].tag=x;    for (int i=head[x];i;i=next[i])     {        deep[list[i]]=deep[x]+1;        dfs(list[i]);    }    out[x]=dfn;}inline void pushup(int k){    id[tree[k].tag]=k; tree[k].tag=0; tree[k].col=1;    for (int i=0;i<=1;i++)    {        tree[k].mn[i]=min(tree[k].d[i],min(tree[ls[k]].mn[i],tree[rs[k]].mn[i]));        tree[k].mx[i]=max(tree[k].d[i],max(tree[ls[k]].mx[i],tree[rs[k]].mx[i]));    }}void build(int &k,int l,int r,int dir,int f){    int mid=l+r>>1; k=mid; D=dir;       nth_element(tree+l,tree+mid,tree+r+1);    tree[k].fa=f; //要写在上一句下面!    if (l<mid) build(ls[k],l,mid-1,dir^1,k); else ls[k]=0;    if (r>mid) build(rs[k],mid+1,r,dir^1,k); else rs[k]=0;    pushup(k); }inline void pushdown(int k){    if (tree[k].tag)    {        if (ls[k]) tree[ls[k]].tag=tree[ls[k]].col=tree[k].tag;        if (rs[k]) tree[rs[k]].tag=tree[rs[k]].col=tree[k].tag;        tree[k].tag=0;    }}void change(int k){    if (tree[k].mn[0]>x2||tree[k].mx[0]<x1||tree[k].mn[1]>y2||tree[k].mx[1]<y1) return;    if (tree[k].mn[0]>=x1&&tree[k].mx[0]<=x2&&tree[k].mx[1]<=y2&&tree[k].mn[1]>=y1)     {        tree[k].tag=tree[k].col=c;         return;    }    pushdown(k);    if (tree[k].d[0]>=x1&&tree[k].d[0]<=x2&&tree[k].d[1]>=y1&&tree[k].d[1]<=y2) tree[k].col=c;    if (ls[k]) change(ls[k]);     if (rs[k]) change(rs[k]);}inline int query(int x){    int now=x,top=0;    while (tree[now].fa) stack[++top]=now=tree[now].fa;    while (top) pushdown(stack[top--]);    return tree[x].col;}int main(){//  freopen("g.in","r",stdin);//  freopen("g1.out","w",stdout);    for (int i=0;i<=1;i++)        tree[0].mn[i]=inf,tree[0].mx[i]=-inf;    int testcase=read();    while (testcase--)    {        n=read(),c=read(),q=read(); cnt=0; ans=0;        memset(head,0,sizeof(head));        for (int i=2;i<=n;i++)            insert(read(),i);        dfs(1);        build(root,1,n,0,0);//      for (int i=1;i<=n;i++)//          printf("%d %d %d %d\n",tree[i].mx[0],tree[i].mx[1],tree[i].mn[0],tree[i].mn[1]);//      for (int i=1;i<=n;i++)//          printf("%d ",tree[i].fa);        for (int i=1;i<=q;i++)        {               a=read(); l=read(); c=read();            if (!c) ans=(1ll*query(id[a])*i+ans)%mod;            else            {                x1=in[a]; x2=out[a]; y1=deep[a]; y2=deep[a]+l;                change(root);            }        }        cout << ans << endl;    }    return 0;}               
0 0