【IPSC2015】【BZOJ4154】Generating Synergy

来源:互联网 发布:网络 在线客服 编辑:程序博客网 时间:2024/06/07 00:51

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 1000000007using 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);    }}
1 0
原创粉丝点击