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. 基于spring boot的定时器

    首先,搭建好一个springboot项目 方法一:通过springboot自带入口来开启定时器. 首先我们都知道,springboot有一个自己的入口,也就是@SpringBootApplicatio ...

  2. C# 集合 特殊集合

    一集合 1.可为不同类型,不固定长度 2.集合类型分为泛型集合(强类型集合)与非泛型集合(弱类型集合). 3.非泛型集合的类和接口位于using System.Collections命名空间. 4.泛 ...

  3. 7.C#知识点:抽象类和接口浅谈

    知识点目录==========>传送门 首先介绍什么是抽象类? 抽象类用关键字abstract修饰的类就是叫抽象类,抽象类天生的作用就是被继承的,所以不能实例化,只能被继承.而且 abstrac ...

  4. Java - 异常解析基础

    java提高篇(十六)-----异常(一) 一.为什么要使用异常 首先我们可以明确一点就是异常的处理机制可以确保我们程序的健壮性,提高系统可用率.虽然我们不是特别喜欢看到它,但是我们不能不承认它的地位 ...

  5. 如何用JS获取页面上的所有标签

    最近忙的一匹,忙着大保健,都来不及写博客,今天特意抽出点时间来写一写 前两天看到一个题,是问如何从页面上获取所有的标签的并查看他们的数量,感觉还是有点意思的,所以给大家来搞一下子 我们先来捋捋思路,那 ...

  6. Mybatis中使用循环遍历

    Mybatis中传参数的方法 1.使用注解绑定,mapper.xml 对应方法 不需要指定 parameterType,(推荐使用注解绑定方式) 方法接口: List<CalculateIdea ...

  7. AngularJS图片上传功能实践

    逻辑理清楚了:service提供FileReader函数,directive提供点击事件的绑定和监听,controller用来修改html上的ng-src属性值 1.HTML <input ty ...

  8. [Android] ACTION_GET_CONTENT与ACTION_PICK的区别

    参考:AndroidSDK/docs/reference/android/content/Intent 看到相关代码,对这两个参数的区别有点搞不清. 原文地址请保留http://www.cnblogs ...

  9. 记一款bug管理系统(bugdone.cn)的开发过程(4) - 新增BugTalk功能

    测试人员提出一个Bug,如果开发人员对Bug有疑义,会直接面对面讨论或者通过QQ等线上聊天工具讨论,但过后再去找讨论记录会很麻烦.因此BugDone提出一个全新的概念:将问题的讨论留在问题内.BugD ...

  10. JavaScript语法详解:运算符和表达式

    本文首发于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 我们在上一篇文章里讲到了JS中变量的概念,本篇文章讲一下运算符和表达式. 比 ...