【BZOJ4154】[Ipsc2015]Generating Synergy KDtree

【BZOJ4154】[Ipsc2015]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

题解:想了半天奇怪的做法,正解居然是KDtree?

KDtree的第一维是DFS序,第二维是深度,区间修改用打标记实现,查询时下传标记,剩下的就不用说了吧?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll P=1000000007;
const int maxn=100010;
int n,m,D,rt,cnt;
ll ans;
int to[maxn],next[maxn],head[maxn],p[maxn],q[maxn],fa[maxn],L[2],R[2],dep[maxn],st[maxn],pos[maxn];
struct kd
{
    int ls,rs,fa,tag,col,org,v[2],sm[2],sn[2];
    kd(){}
    kd(int a,int b,int c){sm[0]=sn[0]=v[0]=a,sm[1]=sn[1]=v[1]=b,org=c,ls=rs=fa=0,tag=0,col=1;}
}t[maxn];
bool cmp(const kd &a,const kd &b)
{
    return  (a.v[D]==b.v[D])?(a.v[D^1]<b.v[D^1]):(a.v[D]<b.v[D]);
}
inline int rd()
{
    int ret=0,f=1;  char gc=getchar();
    while(gc<'0'||gc>'9') {if(gc=='-')f=-f;   gc=getchar();}
    while(gc>='0'&&gc<='9')   ret=ret*10+gc-'0',gc=getchar();
    return ret*f;
}
inline void add(int a,int b)
{
    to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x)
{
    p[x]=++p[0];
    for(int i=head[x];i!=-1;i=next[i])  dep[to[i]]=dep[x]+1,dfs(to[i]);
    q[x]=p[0];
}
inline void pushup(int x,int y)
{
    t[x].sm[0]=max(t[x].sm[0],t[y].sm[0]);
    t[x].sn[0]=min(t[x].sn[0],t[y].sn[0]);
    t[x].sm[1]=max(t[x].sm[1],t[y].sm[1]);
    t[x].sn[1]=min(t[x].sn[1],t[y].sn[1]);
}
inline void pushdown(int x)
{
    if(t[x].tag)
    {
        if(t[x].ls) t[t[x].ls].col=t[t[x].ls].tag=t[x].tag;
        if(t[x].rs) t[t[x].rs].col=t[t[x].rs].tag=t[x].tag;
        t[x].tag=0;
    }
}
int build(int l,int r,int d)
{
    if(l>r)  return 0;
    int mid=(l+r)>>1;
    D=d,nth_element(t+l,t+mid,t+r+1,cmp),pos[t[mid].org]=mid;
    t[mid].ls=build(l,mid-1,d^1),t[mid].rs=build(mid+1,r,d^1);
    if(t[mid].ls)   t[t[mid].ls].fa=mid,pushup(mid,t[mid].ls);
    if(t[mid].rs)   t[t[mid].rs].fa=mid,pushup(mid,t[mid].rs);
    return mid;
}
void updata(int x,int y)
{
    if(!x||t[x].sn[0]>R[0]||t[x].sm[0]<L[0]||t[x].sn[1]>R[1]||t[x].sm[1]<L[1])  return ;
    pushdown(x);
    if(t[x].sm[0]<=R[0]&&t[x].sn[0]>=L[0]&&t[x].sm[1]<=R[1]&&t[x].sn[1]>=L[1])
    {
        t[x].tag=t[x].col=y;
        return ;
    }
    if(t[x].v[0]<=R[0]&&t[x].v[0]>=L[0]&&t[x].v[1]<=R[1]&&t[x].v[1]>=L[1])  t[x].col=y;
    updata(t[x].ls,y),updata(t[x].rs,y);
}
inline int query(int x)
{
    st[st[0]=1]=x;
    while(t[st[st[0]]].fa)  st[st[0]+1]=t[st[st[0]]].fa,st[0]++;
    while(st[0])    pushdown(st[st[0]]),st[0]--;
    return t[x].col;
}
void work()
{
    n=rd(),rd(),m=rd();
    memset(head,-1,sizeof(head)),cnt=0,ans=0;
    int i,a,b,c;
    for(i=2;i<=n;i++)    fa[i]=rd(),add(fa[i],i);
    dep[1]=1,dfs(1);
    for(i=1;i<=n;i++)    t[i]=kd(p[i],dep[i],i);
    rt=build(1,n,0);
    for(i=1;i<=m;i++)
    {
        a=rd(),b=rd(),c=rd();
        if(!c)  ans=(ans+(ll)i*query(pos[a]))%P;
        else    L[0]=p[a],R[0]=q[a],L[1]=dep[a],R[1]=dep[a]+b,updata(rt,c);
    }
    printf("%lld\n",ans);
}
int main()
{
    int T=rd();
    while(T--)  work();
    return 0;
}//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

 

posted @   CQzhangyu  阅读(266)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示