【IPSC2015】【BZOJ4154】Generating Synergy

Description

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

第一行一个数T,表示数据组数
接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数
接下来一行n-1个数描述2..n的父节点
接下来q行每行三个数a,l,c
若c为0,表示询问a的颜色
否则将距离a不超过l的a的子节点染成c
Output

设当前是第i个操作,y_i为本次询问的答案(若本次操作是一个修改则y_i为0),令z_i=i*y_i,请输出z_1+z_2+…+z_q模10^9+7
Sample Input

1

4 3 7

1 2 2

3 0 0

2 1 3

3 0 0

1 0 2

2 0 0

4 1 1

4 0 0
Sample Output

32
HINT

第1,3,5,7的询问的答案分别为1,3,3,1,所以答案为 1*1+2*0+3*3+4*0+5*3+6*0+7*1=32.

数据范围:

对于100%的数据T<=6,n,m,c<=10^5,

1<=a<=n,0<=l<=n,0<=c<=c

Source

考虑用dfs序和深度分别当成两维坐标
然后打打颜色标记就行了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Dnum 2
#define MAXN 100010
#define GET (ch>='0'&&ch<='9')
#define P 1000000007
using namespace std;
inline void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
int ans;
int T,n,c,q,top,root,dfn,tp;
bool cmp_d;
int In[MAXN],Out[MAXN],deep[MAXN],sta[MAXN],id[MAXN];
struct edge {   int to; edge *next; }e[MAXN],*prev[MAXN];
inline void insert(int u,int v) {   e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];  }
struct KDtree
{
    int ch[2],d[Dnum],minn[Dnum],maxn[Dnum],tim,col,f,flag;
    inline void init()  {   for (int i=0;i<Dnum;++i)    minn[i]=maxn[i]=d[i];   }
    inline bool operator < (const KDtree& a)const   {   return d[cmp_d]<a.d[cmp_d]; }
}tree[MAXN];
inline void push_up(int rt)
{
    id[tree[rt].flag]=rt;tree[rt].flag=0;tree[rt].col=1;
    for (int i=0,x=0;i<2;++i)
        if ((x=tree[rt].ch[i]))
        {
            for (int j=0;j<Dnum;++j)
                tree[rt].minn[j]=min(tree[rt].minn[j],tree[x].minn[j]),
                tree[rt].maxn[j]=max(tree[rt].maxn[j],tree[x].maxn[j]);
        }
}
inline void push_down(int rt)
{
    int tmp=0;
    if ((tmp=tree[rt].flag))
    {
        for (int i=0,x=0;i<2;++i)   if ((x=tree[rt].ch[i])) tree[x].col=tree[x].flag=tmp;
        tree[rt].flag=0;
    }
}
int rebuild(int l=1,int r=n,bool d=0,int f=0)
{
    cmp_d=d;int mid=(l+r)>>1;nth_element(tree+l,tree+mid,tree+r+1);
    tree[mid].init();tree[mid].f=f;
    if (l!=mid) tree[mid].ch[0]=rebuild(l,mid-1,d^1,mid);
    if (r!=mid) tree[mid].ch[1]=rebuild(mid+1,r,d^1,mid);
    return push_up(mid),mid;
}
int col,x1,x2,y1,y2;
void modify(int rt=root)
{
    if (tree[rt].minn[0]>x2||tree[rt].maxn[0]<x1||tree[rt].maxn[1]<y1||tree[rt].minn[1]>y2) return;
    if (tree[rt].minn[0]>=x1&&tree[rt].maxn[0]<=x2&&tree[rt].minn[1]>=y1&&tree[rt].maxn[1]<=y2) {   tree[rt].col=tree[rt].flag=c;return;    }
    push_down(rt);
    if (tree[rt].d[0]>=x1&&tree[rt].d[0]<=x2&&tree[rt].d[1]>=y1&&tree[rt].d[1]<=y2) tree[rt].col=c;
    for (int i=0,x=0;i<2;++i)   if ((x=tree[rt].ch[i])) modify(x);
}
inline int query(int rt)
{
    for (int i=rt;tree[i].f;i=tree[i].f)    sta[++tp]=tree[i].f;
    while (tp)  push_down(sta[tp--]);return tree[rt].col;
}
void dfs(int x)
{
    tree[x].flag=x;In[x]=tree[x].d[0]=++dfn;tree[x].d[1]=deep[x];
    for (edge *i=prev[x];i;i=i->next)   deep[i->to]=deep[x]+1,dfs(i->to);
    Out[x]=dfn;
}
inline void clear()
{
    for (int i=1;i<=n;i++)  for (int j=0;j<2;++j)   tree[i].ch[j]=0;
}
int main()
{
    for (in(T);T;T--)
    {
        in(n);in(c);in(q);int u,v;dfn=top=0;
        memset(prev+1,0,sizeof(edge*)*(n+1));clear();
        for (int i=2;i<=n;i++)  in(u),insert(u,i);
        dfs(1);root=rebuild();ans=0;
        for (int i=1;i<=q;i++)
        {
            in(u);in(v);in(c);
            if (c)  x1=In[u],x2=Out[u],y1=deep[u],y2=deep[u]+v,modify();
            else    ans=(1ll*query(id[u])*i+ans)%P;
        }
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(dfs序,KDTree)