NKOJ 4345 (Ipsc2015)Generating Synergy (DFS序+kd树)

来源:互联网 发布:java预约系统源代码 编辑:程序博客网 时间:2024/05/19 23:56

P4345[Ipsc2015]Generating Synergy

问题描述

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

输入格式

第一行一个数T,表示数据组数

接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数

接下来一行n-1个数描述2..n的父节点

接下来q行每行三个数a,l,c

若c为0,表示询问a的颜色

否则将距离a不超过l的a的子节点染成c

输出格式

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

样例输入

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

样例输出

32

提示

第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


首先求出这棵树的DFS序和每个节点的深度,那么将DFS序的In作为x坐标,将深度作为y坐标,建立kd树,那么每次询问直接找对应点,修改就变成将以(In[a],dep[a])(Out[a],dep[a]+l)为左上和右下顶点的矩形区域整体修改,kd树+lazy即可解决。

另外,也可以用树套树维护,但显然不如kd树好写。


代码:

#include<stdio.h>#include<iostream>#include<algorithm>#include<cstring>#define N 222222#define ll long longusing namespace std;int rt,D,T,n,c,q,x1,x2,y1,y2;int L[N],R[N],dep[N],VT,mod=1e9+7;int LA[N],NE[N],EN[N],TOT;struct node{    int d[2],x[2],y[2],son[2],v,lazy;    bool operator<(const node &b)const    {return d[D]<b.d[D];}}kdt[N];void PD(int p){    int ls=kdt[p].son[0],rs=kdt[p].son[1];    kdt[ls].v=kdt[rs].v=kdt[p].lazy;    kdt[ls].lazy=kdt[rs].lazy=kdt[p].lazy;    kdt[p].lazy=0;}void MT(int p,int s){    kdt[p].x[0]=min(kdt[p].x[0],kdt[s].x[0]);    kdt[p].x[1]=max(kdt[p].x[1],kdt[s].x[1]);    kdt[p].y[0]=min(kdt[p].y[0],kdt[s].y[0]);    kdt[p].y[1]=max(kdt[p].y[1],kdt[s].y[1]);}int BT(int l,int r,int d){    D=d;int o=l+r>>1;    kdt[o].v=1;    kdt[o].x[0]=kdt[o].x[1]=kdt[o].d[0];    kdt[o].y[0]=kdt[o].y[1]=kdt[o].d[1];    if(l<o)kdt[o].son[0]=BT(l,o-1,d^1),MT(o,kdt[o].son[0]);    if(o<r)kdt[o].son[1]=BT(o+1,r,d^1),MT(o,kdt[o].son[1]);    return o;}void ADD(int x,int y){    TOT++;    EN[TOT]=y;    NE[TOT]=LA[x];    LA[x]=TOT;}void DFS(int x,int f){    L[x]=++VT;dep[x]=dep[f]+1;    for(int i=LA[x];i;i=NE[i])DFS(EN[i],x);    R[x]=VT;}int GA(int p){    if(kdt[p].lazy)PD(p);    if(kdt[p].d[0]==x1&&kdt[p].d[1]==y1)return kdt[p].v;    int s=0,ls=kdt[p].son[0],rs=kdt[p].son[1];    if(kdt[ls].x[0]<=x1&&kdt[ls].x[1]>=x1&&kdt[ls].y[0]<=y1&&kdt[ls].y[1]>=y1)s+=GA(ls);    if(kdt[rs].x[0]<=x1&&kdt[rs].x[1]>=x1&&kdt[rs].y[0]<=y1&&kdt[rs].y[1]>=y1)s+=GA(rs);    return s;}void CHA(int p,int k){    if(kdt[p].lazy)PD(p);    if(kdt[p].d[0]<=x2&kdt[p].d[0]>=x1&&kdt[p].d[1]<=y2&&kdt[p].d[0]>=y1)kdt[p].v=k;    if(kdt[p].x[0]>x2||kdt[p].x[1]<x1||kdt[p].y[0]>y2||kdt[p].y[1]<y1)return;    if(kdt[p].x[1]<=x2&&kdt[p].x[0]>=x1&&kdt[p].y[1]<=y2&&kdt[p].y[0]>=y1){kdt[p].v=kdt[p].lazy=k;return;}    CHA(kdt[p].son[0],k);CHA(kdt[p].son[1],k);}int main(){    int i,k,x,y;ll ans;    scanf("%d",&T);    while(T--)    {        TOT=VT=ans=0;        memset(kdt,0,sizeof(kdt));        memset(LA,0,sizeof(LA));        scanf("%d%d%d",&n,&c,&q);        for(i=2;i<=n;i++)scanf("%d",&x),ADD(x,i);        DFS(1,0);        for(i=1;i<=n;i++)kdt[i].d[0]=L[i],kdt[i].d[1]=dep[i];        rt=BT(1,n,0);        for(i=1;i<=q;i++)        {            scanf("%d%d%d",&x,&y,&k);            if(k==0)            {                x1=L[x];y1=dep[x];                ans=(ans+1ll*GA(rt)*i)%mod;            }            else            {                x1=L[x];x2=R[x];                y1=dep[x];y2=dep[x]+y;                CHA(rt,k);            }        }        printf("%lld\n",ans);    }}
原创粉丝点击