BZOJ4154:[Ipsc2015]Generating Synergy(K-D Tree)
Description
Input
Output
Sample Input
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
HINT
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)的更多相关文章
- 【kd-tree】bzoj4154 [Ipsc2015]Generating Synergy
区间修改的kd-tree,打标记,下传. 每次询问的时候,从询问点向上找到根,然后依次下传下来,再回答询问. #include<cstdio> #include<algorithm& ...
- BZOJ4154: [Ipsc2015]Generating Synergy
Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 Input 第一行一个数T,表示数据组数 接下来每组数据的第一 ...
- 【BZOJ4154】[Ipsc2015]Generating Synergy KDtree
[BZOJ4154][Ipsc2015]Generating Synergy Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问 ...
- [bzoj4154][Ipsc2015]Generating Synergy_KD-Tree_dfs序
Generating Synergy bzoj-4154 Ipsc-2015 题目大意:给定一棵n个节点树,m个操作,支持:将一个点周围所有距该点距离不超过l的子结点的颜色改成另一种颜色:查询单点颜色 ...
- BZOJ4154:[IPSC2015]Generating Synergy
浅谈\(K-D\) \(Tree\):https://www.cnblogs.com/AKMer/p/10387266.html 题目传送门:https://lydsy.com/JudgeOnline ...
- 【bzoj4154】[Ipsc2015]Generating Synergy KD-tree
题目描述 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 输入 第一行一个数T,表示数据组数 接下来每组数据的第一行三个数n,c,q表示结 ...
- 【bzoj 4154】[Ipsc2015]Generating Synergy
题目 大概已经掌握熟练码出\(kdt\)的技能了 发现距离子树根节点\(x\)不超过\(l\)的点可以用两种方式来限制,首先\(dfs\)序在\([dfn_x,dfn_x+sum_x)\)中,深度自然 ...
- 4154: [Ipsc2015]Generating Synergy
Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 区间修改单点查询kdtree #include<iostre ...
- 【BZOJ4154】Generating Synergy【kd树】
题意 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 分析 我们以dfs序为横坐标,深度为纵坐标,建kd树.我们每次更新,都是在kd树中更 ...
随机推荐
- 使用ScheduledExecutorService实现任务延迟
在做项目的过程中,遇到一个场景:在审批流中,如果上级领导不审批,则在10分钟后自动审批.也就是要做一个任务在多长时间后执行的效果 在不断的摸索中,想到了使用线程池,发现有个ScheduledExecu ...
- Hibernate映射 --- 自身跟自身的一对多关联
自身跟自身的一对多关联 什么时候会出现自身一对多关系呢?下面举个例子. 淘宝店里商品分类,一级分类:家用电器,个人化妆,运动户外等 家用电器下面二级分类:大家电,生活电器,厨房电器等 二级分类大家 ...
- Python生成语音
from aip import AipSpeech # 利用百度语音合成音频文件 """ 你的 APPID AK SK """ APP_ID ...
- Java基础——iO(三)
一.管道流 演示:PipedInputStream , PipedOutputStream 注意:管道流本身就不建议在一个线程中使用,这是因为向输出流中写的数据,都会存到输入流内部的一个1024字节 ...
- 多线程系列(1)多线程基础和Thread
因为现项目中有用到多线程和并发的知识,所以打算近期补习一下多线程相关的内容.第一篇文章从最基础的开始,就是如何开启一个线程,如何启动线程和阻塞线程等,这篇文章分以下几点进行总结. 多线程初印象 多线程 ...
- 1-初识java
目录 java 历史 Java 平台 Java 开发环境 Java 运行原理[简] Java 历史 这里不详细记录java的历史,只是标记出时间点和事件. 时间点 事件 1991 Sun公司成立Gre ...
- BZOJ3108 [cqoi2013]图的逆变换
Description 定义一个图的变换:对于一个有向图\(G=(V, E)\),建立一个新的有向图: \(V'=\{v_e|e \in E\}\),\(E'=\{(v_b, v_e)|b=(u,v) ...
- BZOJ4827: [Hnoi2017]礼物(FFT 二次函数)
题意 题目链接 Sol 越来越菜了..裸的FFT写了1h.. 思路比较简单,直接把 \(\sum (x_i - y_i + c)^2\) 拆开 发现能提出一坨东西,然后与c有关的部分是关于C的二次函数 ...
- JavaScript 事件处理机制
DOM 事件流 DOM 是一个树型结构,当一个HTML元素产生一个事件时,该事件会在该元素结点与根节点之间按特定的顺序传播,路径所经过的节点都会收到该事件,这个传播过程可称为DOM事件流.而事件传播的 ...
- Warning:java:资源1.5已过时,将在未来所有发行版中删除
idea运行提示错误信息:解决办法如下:第一步![ ...