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

Solution

将每个点看成二维点$(DFN[x],Depth[x])$,也就是$DFS$序和深度。

这样的话这个题就变成了单点查询和区间打标记覆盖了。

区间打标记的时候记得把路径上经过的点颜色修改一下……因为这里挂了调了好久(

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N (100009)
#define MOD (1000000007)
using namespace std; struct Edge{int to,next;}edge[N];
int T,n,c,q,x,a,l,opt,ans,dfs_num,D,MaxDep;
int DFN[N],Depth[N],Size[N];
int head[N],num_edge; struct Node
{
int Max[],Min[],d[],ls,rs,col,cov;
bool operator < (const Node &a) const {return d[D]<a.d[D];}
}p[N],Q; struct KDT
{
Node T[N];
void Pushup(int now)
{
int ls=T[now].ls,rs=T[now].rs;
for (int i=; i<=; ++i)
{
T[now].Max[i]=T[now].Min[i]=T[now].d[i];
if (ls)
{
T[now].Max[i]=max(T[now].Max[i],T[ls].Max[i]);
T[now].Min[i]=min(T[now].Min[i],T[ls].Min[i]);
}
if (rs)
{
T[now].Max[i]=max(T[now].Max[i],T[rs].Max[i]);
T[now].Min[i]=min(T[now].Min[i],T[rs].Min[i]);
}
}
}
void Pushdown(int now)
{
if (T[now].cov!=-)
{
int ls=T[now].ls,rs=T[now].rs;
T[ls].cov=T[ls].col=T[now].cov;
T[rs].cov=T[rs].col=T[now].cov;
T[now].cov=-;
}
}
int Build(int opt,int l,int r)
{
if (l>r) return ;
int mid=(l+r)>>;
D=opt; nth_element(p+l,p+mid,p+r+);
T[mid]=p[mid];
T[mid].ls=Build(opt^,l,mid-);
T[mid].rs=Build(opt^,mid+,r);
Pushup(mid); return mid;
}
int Query(int now)
{
if (Q.d[]<T[now].Min[] || Q.d[]>T[now].Max[]) return ;
if (Q.d[]<T[now].Min[] || Q.d[]>T[now].Max[]) return ;
if (Q.d[]==T[now].d[] && Q.d[]==T[now].d[]) return T[now].col;
Pushdown(now); return Query(T[now].ls)+Query(T[now].rs);
}
void Update(int now,int k)
{
if (Q.Min[]>T[now].Max[] || Q.Max[]<T[now].Min[] || Q.Min[]>T[now].Max[] || Q.Max[]<T[now].Min[]) return;
if (Q.Min[]<=T[now].Min[] && Q.Max[]>=T[now].Max[] && Q.Min[]<=T[now].Min[] && Q.Max[]>=T[now].Max[])
{
T[now].col=k; T[now].cov=k;
return;
}
Pushdown(now);
if (T[now].d[]>=Q.Min[] && T[now].d[]<=Q.Max[] && T[now].d[]>=Q.Min[] && T[now].d[]<=Q.Max[])
T[now].col=k;
Update(T[now].ls,k); Update(T[now].rs,k);
}
}KDT; inline int read()
{
int x=; char c=getchar();
while (c<'' || c>'') c=getchar();
while (c>='' && c<='') x=x*+c-'', c=getchar();
return x;
} void add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
} void DFS(int x)
{
Size[x]=; DFN[x]=++dfs_num;
for (int i=head[x]; i; i=edge[i].next)
{
Depth[edge[i].to]=Depth[x]+;
DFS(edge[i].to);
Size[x]+=Size[edge[i].to];
}
MaxDep=max(MaxDep,Depth[x]);
} int main()
{
T=read();
while (T--)
{
memset(head,,sizeof(head));
memset(Depth,,sizeof(Depth));
num_edge=dfs_num=MaxDep=ans=;
n=read(); c=read(); q=read();
for (int i=; i<=n; ++i)
p[i].col=, p[i].cov=-;
for (int i=; i<=n; ++i)
x=read(), add(x,i);
DFS();
for (int i=; i<=n; ++i)
p[i].d[]=DFN[i], p[i].d[]=Depth[i];
int Root=KDT.Build(,,n);
for (int i=; i<=q; ++i)
{
a=read(); l=read(); opt=read();
if (opt==)
{
Q.d[]=DFN[a]; Q.d[]=Depth[a];
(ans+=1ll*i*KDT.Query(Root)%MOD)%=MOD;
}
else
{
Q.Min[]=DFN[a]; Q.Max[]=DFN[a]+Size[a]-;
Q.Min[]=Depth[a]; Q.Max[]=min(MaxDep,Depth[a]+l);
KDT.Update(Root,opt);
}
}
printf("%d\n",ans);
}
}

BZOJ4154:[Ipsc2015]Generating Synergy(K-D Tree)的更多相关文章

  1. 【kd-tree】bzoj4154 [Ipsc2015]Generating Synergy

    区间修改的kd-tree,打标记,下传. 每次询问的时候,从询问点向上找到根,然后依次下传下来,再回答询问. #include<cstdio> #include<algorithm& ...

  2. BZOJ4154: [Ipsc2015]Generating Synergy

    Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色   Input 第一行一个数T,表示数据组数 接下来每组数据的第一 ...

  3. 【BZOJ4154】[Ipsc2015]Generating Synergy KDtree

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

  4. [bzoj4154][Ipsc2015]Generating Synergy_KD-Tree_dfs序

    Generating Synergy bzoj-4154 Ipsc-2015 题目大意:给定一棵n个节点树,m个操作,支持:将一个点周围所有距该点距离不超过l的子结点的颜色改成另一种颜色:查询单点颜色 ...

  5. BZOJ4154:[IPSC2015]Generating Synergy

    浅谈\(K-D\) \(Tree\):https://www.cnblogs.com/AKMer/p/10387266.html 题目传送门:https://lydsy.com/JudgeOnline ...

  6. 【bzoj4154】[Ipsc2015]Generating Synergy KD-tree

    题目描述 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 输入 第一行一个数T,表示数据组数 接下来每组数据的第一行三个数n,c,q表示结 ...

  7. 【bzoj 4154】[Ipsc2015]Generating Synergy

    题目 大概已经掌握熟练码出\(kdt\)的技能了 发现距离子树根节点\(x\)不超过\(l\)的点可以用两种方式来限制,首先\(dfs\)序在\([dfn_x,dfn_x+sum_x)\)中,深度自然 ...

  8. 4154: [Ipsc2015]Generating Synergy

    Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 区间修改单点查询kdtree #include<iostre ...

  9. 【BZOJ4154】Generating Synergy【kd树】

    题意 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 分析 我们以dfs序为横坐标,深度为纵坐标,建kd树.我们每次更新,都是在kd树中更 ...

随机推荐

  1. Jquery操作属性

    1.attr(name,value):修改单个属性! name :属性名称 value:属性的值 <script> $(function(){ //给div添加一个alt=hello的属性 ...

  2. 常用的7个SQl优化技巧

    作为程序员经常和数据库打交道的时候还是非常频繁的,掌握住一些Sql的优化技巧还是非常有必要的.下面列出一些常用的SQl优化技巧,感兴趣的朋友可以了解一下. 1.注意通配符中Like的使用 以下写法会造 ...

  3. Android-Binder机制

    http://www.jianshu.com/p/af2993526daf https://www.jianshu.com/u/e347b97e2f0c 上面这篇文章讲得很清楚.以下我的一些理解: 还 ...

  4. 为什么要用lock 【readonly】object?为什么不要lock(this)?

    一. 为什么要用lock,lock了什么? 当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待.但当不同的线程都需要访问某个资源的时候,就需要同步机制了.也就是说 ...

  5. macbook 外接显示器黑屏,不显示

    我的mac本有点老了,11年底的那款 整了个显示器,刚开始连上没问题,后来开机状态拔了雷电线,再插  或者关机后莫名的原因再启动,显示器黑屏 网上好多方法都不行,自己总结了一个方法 拔掉连接线,关闭m ...

  6. Code Signal_练习题_stringsRearrangement

    Given an array of equal-length strings, check if it is possible to rearrange the strings in such a w ...

  7. js-学习笔记-Thunk函数

    Thunk 函数是自动执行 Generator 函数的一种方法. 编译器的“传名调用”实现,往往是将参数放到一个临时函数之中,再将这个临时函数传入函数体.这个临时函数就叫做 Thunk 函数. fun ...

  8. OSGI企业应用开发(三)Eclipse中搭建Equinox运行环境

    上篇文章介绍了如何在Eclipse中搭建Felix的运行环境,我们需要將Bundle发布到Felix框架的bundle目录下,Felix框架启动时才会自动加载这些Bundle,否则需要在Felix框架 ...

  9. <Android 基础(三十三)> TabHost ~ 仿微信底部菜单

    简介 Container for a tabbed window view. This object holds two children: a set of tab labels that the ...

  10. Python 在子类中调用父类方法详解(单继承、多层继承、多重继承)

    Python 在子类中调用父类方法详解(单继承.多层继承.多重继承)   by:授客 QQ:1033553122   测试环境: win7 64位 Python版本:Python 3.3.5 代码实践 ...