BZOJ4154:Generating Synergy (KDtree)

来源:互联网 发布:深入浅出node infoq 编辑:程序博客网 时间:2024/06/02 17:44

传送门

题意:
给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色

题解:KDtree
看完这道题题解,我只想说:还有这种操作???

想了半天的点分治,后来发现看错题了,原来只有子节点。。。

KDtree:
首先将每个点的横坐标看做dfs序,那么修改在一个区间内进行,由于这些点只有部分点会被修改,而修改的点的dep又是一段连续的区间,就像是二维点对中的一个矩形,那么直接kdtree就好了,时间复杂度O(nn),当然这个是最坏复杂度。实测跑得还是挺快的。(听说树套树也能做,然而我并不会。。)

#include<bits/stdc++.h>using namespace std;struct IO{    streambuf *ib,*ob;    inline void init(){        ios::sync_with_stdio(false);        cin.tie(NULL);cout.tie(NULL);        ib=cin.rdbuf();ob=cout.rdbuf();    }    inline int read(){        char ch=ib->sbumpc();int i=0,f=1;        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}        while(isdigit(ch)){i=(i+(i<<2)<<1)+ch-'0';ch=ib->sbumpc();}        return i*f;    }    inline void W(long long x){        static int buf[50];        if(!x){ob->sputc('0');ob->sputc('\n');return;}        if(x<0){ob->sputc('-');x=-x;}        while(x){buf[++buf[0]]=x%10;x/=10;}        while(buf[0])ob->sputc(buf[buf[0]--]+'0');        ob->sputc('\n');    }}io;const int Maxn=1e5+50;const int Mod=1e9+7;int n,c,q,ans,dep[Maxn],in[Maxn],out[Maxn],ind;struct point{    int x[2],id;    point(int Id=0,int x0=0,int x1=0){        x[0]=x0;x[1]=x1;id=Id;    }}PointPool[Maxn],*pointpool=PointPool;inline point newpoint(int id,int x,int y){    ++pointpool;    pointpool->x[0]=x;pointpool->x[1]=y;pointpool->id=id;    return *pointpool;}inline bool cmpx(const point &a,const point &b){return a.x[0]<b.x[0]||(a.x[0]==b.x[0]&&a.id<b.id);}inline bool cmpy(const point &a,const point &b){return a.x[1]<b.x[1]||(a.x[1]==b.x[1]&&a.id<b.id);}struct node{    node *lc,*rc;    int mnx[2],mxx[2];    point p;int c,tag;    inline void upt();    inline void addtag(int col){        c=col;tag=col;    }    inline void pushdown();}NodePool[Maxn],*nodepool=NodePool,*null=NodePool;inline node* newnode(int id,int x,int y){    ++nodepool;    nodepool->p=newpoint(id,x,y);    nodepool->lc=nodepool->rc=null;    nodepool->tag=-1;nodepool->c=1;    nodepool->mnx[0]=nodepool->mxx[0]=x;    nodepool->mnx[1]=nodepool->mxx[1]=y;    return nodepool;}inline void node::pushdown(){    if(tag==-1)return;    if(lc!=null)lc->addtag(tag);    if(rc!=null)rc->addtag(tag);    tag=-1;}inline void node::upt(){    for(int i=0;i<2;i++){        mnx[i]=mxx[i]=p.x[i];        if(lc!=null)mnx[i]=min(mnx[i],lc->mnx[i]),mxx[i]=max(mxx[i],lc->mxx[i]);        if(rc!=null)mnx[i]=min(mnx[i],rc->mnx[i]),mxx[i]=max(mxx[i],rc->mxx[i]);    }}struct kd_tree{    node *rt;    point que[Maxn],t;    int tail;    inline void init(){        rt=null;        tail=0;    }    inline void build(node*& now,int l,int r,int dim){        if(l==r){            now=newnode(que[l].id,que[l].x[0],que[l].x[1]);            return;        }        int mid=(l+r)>>1;        dim?(nth_element(que+l,que+mid,que+r+1,cmpy)):(nth_element(que+l,que+mid,que+r+1,cmpx));        now=newnode(que[mid].id,que[mid].x[0],que[mid].x[1]);        if(l<mid)build(now->lc,l,mid-1,dim^1);        if(r>mid)build(now->rc,mid+1,r,dim^1);        now->upt();    }    inline bool In(node *now,int x0,int x1,int y0,int y1){        return now->mnx[0]>=x0&&now->mxx[0]<=x1&&now->mnx[1]>=y0&&now->mxx[1]<=y1;    }    inline bool insertline(int x0,int x1,int y0,int y1){        return (x0>=y0&&x0<=y1)||(x1>=y0&&x1<=y1)||(y0>=x0&&y0<=x1);    }    inline bool insert(node *now,int x0,int x1,int y0,int y1){        return insertline(now->mnx[0],now->mxx[0],x0,x1)&&insertline(now->mnx[1],now->mxx[1],y0,y1);    }    inline void modify(node *now,int x0,int x1,int y0,int y1,int c){        if(In(now,x0,x1,y0,y1)){            now->addtag(c);            return;        }        now->pushdown();        if(now->p.x[0]>=x0&&now->p.x[0]<=x1&&now->p.x[1]>=y0&&now->p.x[1]<=y1)now->c=c;        if(now->lc!=null&&insert(now->lc,x0,x1,y0,y1))modify(now->lc,x0,x1,y0,y1,c);        if(now->rc!=null&&insert(now->rc,x0,x1,y0,y1))modify(now->rc,x0,x1,y0,y1,c);    }    inline int query(node *now,int id,int dim){        if(id==now->p.id)return now->c;        now->pushdown();        if(now->lc!=null&&(dim?cmpy(t,now->p):cmpx(t,now->p)))return query(now->lc,id,dim^1);        else return query(now->rc,id,dim^1);    }}kdtree;vector<int>edge[Maxn];inline void dfs(int now,int f){    dep[now]=dep[f]+1;in[now]=++ind;kdtree.que[++kdtree.tail]=point(now,in[now],dep[now]);    for(int e=edge[now].size()-1;e>=0;e--){        int v=edge[now][e];        if(v==f)continue;        dfs(v,now);    }    out[now]=ind;}int main(){    io.init();    int T=io.read();    while(T--){        pointpool=PointPool,nodepool=NodePool,kdtree.init();        n=io.read(),c=io.read(),q=io.read(),ans=ind=0;        for(int i=1;i<=n;i++)edge[i].clear();        for(int i=2;i<=n;i++){            edge[io.read()].push_back(i);        }        dfs(1,0);        kdtree.build(kdtree.rt,1,n,0);        for(int i=1;i<=q;i++){            int x=io.read(),l=io.read(),c=io.read();            if(c)kdtree.modify(kdtree.rt,in[x],out[x],dep[x],dep[x]+l,c);            else kdtree.t=point(x,in[x],dep[x]),(ans+=1ll*i*kdtree.query(kdtree.rt,x,0)%Mod)%=Mod;        }        io.W(ans);    }}