题意

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

分析

我们以dfs序为横坐标,深度为纵坐标,建kd树。我们每次更新,都是在kd树中更新一个矩形,横坐标为[st[a],en[a]],纵坐标[depth[a],depth[a]+l]。那么就相当于线段树的区间更新,我们需要给它打个标记。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std;
typedef long long LL;
const int maxn=1e5+;
const int INF=;
const int mod=1e9+; int n,q,c,sz,T;
int head[maxn],Next[*maxn],to[*maxn];
int cnt;
int order[maxn],indx[maxn],st[maxn],en[maxn],depth[maxn];
struct kdNode{
int x[],mnn[],mxn[];
int lc,rc,u;
int val,tag;
}p[maxn],x;
int cmpNo,root;
int cmp(kdNode a,kdNode b){
return a.x[cmpNo]<b.x[cmpNo];
}
void pushdown(int o){
if(p[o].tag){
int l=p[o].lc,r=p[o].rc;
p[l].val=p[o].tag,p[r].val=p[o].tag;
p[o].tag=;
}
} void maintain(int o){
int l=p[o].lc,r=p[o].rc;
for(int i=;i<;i++){
p[o].mnn[i]=min(min(p[l].mnn[i],p[r].mnn[i]),p[o].x[i]);
p[o].mxn[i]=max(max(p[l].mxn[i],p[r].mxn[i]),p[o].x[i]);
}
}
void build(int &o,int l,int r,int d){
if(l>r){
o=;
return;
}
int m=l+(r-l)/;
p[m].tag=;
cmpNo=d,o=m;
nth_element(p+l,p+m,p+r+,cmp);
build(p[o].lc,l,m-,d^);
build(p[o].rc,m+,r,d^);
maintain(o);
}
bool all(int o){
if(p[o].mxn[]<=x.mxn[]&&p[o].mnn[]>=x.mnn[]&&p[o].mnn[]>=x.mnn[]&&p[o].mxn[]<=x.mxn[]){
return true;
}
return false;
}
bool have(int o){
if(p[o].mnn[o]<=x.mxn[]&&p[o].mxn[o]>=x.mnn[]&&p[o].mxn[]>=x.mnn[]&&p[o].mnn[]<=x.mxn[]){
return true;
}
return false;
}
void update(int o){
if(!o)return;
if(all(o)){
p[o].tag=x.tag;
p[o].val=x.tag;
return;
} pushdown(o);
int l=p[o].lc,r=p[o].rc;
if(p[o].x[]>=x.mnn[]&&p[o].x[]<=x.mxn[]&&p[o].x[]>=x.mnn[]&&p[o].x[]<=x.mxn[]){
p[o].val=x.tag;
}
if(all(l)){
p[l].tag=p[l].val=x.tag;
}else if(have(l)){
update(l);
}
if(all(r)){
p[r].tag=p[r].val=x.tag;
}else if(have(r)){
update(r);
}
}
int query(int o){
if(!o)return ;
if(p[o].u==x.u){
return p[o].val;
}
pushdown(o);
int l=p[o].lc,r=p[o].rc; if(p[l].mnn[]<=x.x[]&&p[l].mxn[]>=x.x[]&&x.x[]>=p[l].mnn[]&&x.x[]<=p[l].mxn[])
return query(l);
else
return query(r);
}
void init(){
sz=;
cnt=;
memset(head,-,sizeof(head));
}
void add_edge(int a,int b){
++sz;
to[sz]=b;
Next[sz]=head[a];
head[a]=sz;
}
void dfs(int u,int fa,int dep){
depth[u]=dep;
order[++cnt]=u;
indx[u]=cnt;
st[u]=cnt;
for(int i=head[u];i!=-;i=Next[i]){
int v=to[i];
if(v==fa)
continue;
dfs(v,u,dep+);
}
en[u]=cnt;
}
int main(){
scanf("%d",&T);
for(int kase=;kase<=T;kase++){
scanf("%d%d%d",&n,&c,&q);
init();
for(int i=;i<=n;i++){
int fa;
scanf("%d",&fa);
add_edge(fa,i);
add_edge(i,fa);
}
dfs(,-,);
for(int i=;i<=n;i++){
p[i].x[]=indx[i];
p[i].x[]=depth[i];
p[i].u=i;
p[i].val=;
p[i].tag=p[i].lc=p[i].rc=;
}
p[].mnn[]=p[].mnn[]=INF;
p[].mxn[]=p[].mxn[]=-INF;
build(root,,n,);
LL ans=;
for(int i=;i<=q;i++){
int a,l,c;
scanf("%d%d%d",&a,&l,&c);
if(c){
x.mnn[]=st[a],x.mxn[]=en[a],x.tag=c;
x.mnn[]=depth[a],x.mxn[]=depth[a]+l;
update(root);
}else{
x.u=a;
x.x[]=indx[a];
x.x[]=depth[a];
ans=(ans+(LL)i*query(root))%mod;
// printf("%d\n",query(root,0));
}
}
printf("%lld\n",ans);
}
return ;
}

【BZOJ4154】Generating Synergy【kd树】的更多相关文章

  1. BZOJ4154:[Ipsc2015]Generating Synergy(K-D Tree)

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

  2. 【BZOJ4154】[Ipsc2015]Generating Synergy KDtree

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

  3. BZOJ4154: [Ipsc2015]Generating Synergy

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

  4. K-D树

    一般用来解决各种二维平面的点对统计,也许一般非正解? 没时间慢慢写了,打完这个赛季后补细节 建树板子: #include <cstdio> #include <locale> ...

  5. 利用KD树进行异常检测

    软件安全课程的一次实验,整理之后发出来共享. 什么是KD树 要说KD树,我们得先说一下什么是KNN算法. KNN是k-NearestNeighbor的简称,原理很简单:当你有一堆已经标注好的数据时,你 ...

  6. 2016 ICPC青岛站---k题 Finding Hotels(K-D树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5992 Problem Description There are N hotels all over ...

  7. kd树和knn算法的c语言实现

    基于kd树的knn的实现原理可以参考文末的链接,都是一些好文章. 这里参考了别人的代码.用c语言写的包括kd树的构建与查找k近邻的程序. code: #include<stdio.h> # ...

  8. PCL点云库:Kd树

    Kd树按空间划分生成叶子节点,各个叶子节点里存放点数据,其可以按半径搜索或邻区搜索.PCL中的Kd tree的基础数据结构使用了FLANN以便可以快速的进行邻区搜索.FLANN is a librar ...

  9. KNN算法与Kd树

    最近邻法和k-近邻法 下面图片中只有三种豆,有三个豆是未知的种类,如何判定他们的种类? 提供一种思路,即:未知的豆离哪种豆最近就认为未知豆和该豆是同一种类.由此,我们引出最近邻算法的定义:为了判定未知 ...

随机推荐

  1. L177 Arctic ice brings an understanding of ancient Europe’s economy

    Greenland's icy mountains are not an obvious place to search for an archive of economic history, but ...

  2. jQuery 参数详解

    url: 要求为String类型的参数,发送请求的地址.如果没有填写, 默认发送当前页的url type: 要求为String类型的参数,请求方式(post或get)默认为get. 注意其他http请 ...

  3. UVALive 5135 Mining Your Own Bussiness【tarjan点双】

    LINK1 LINK2 题目大意 给你一个无向连通图,让你给一些点染上黑色,需要满足染色之后,断开任意一个节点,要满足任意一个联通块中剩下的节点中至少有一个黑点 思路 一开始想的是把每一个点双联通分量 ...

  4. 《DSP using MATLAB》Problem 2.2

    1.代码: %% ------------------------------------------------------------------------ %% Output Info abo ...

  5. gridview 绑定多个格式相同的数据源(数据查询合并)

    在做项目时,要求在同一个GridView中同时显示不同分组中的前若干条数据 几个技术要点: 1.数据分组,本方法中未用group by 2.几个结果格式相同的查询合并绑定 3.取查询结果的前或后若干条 ...

  6. Spring AOP 实现读写分离

    原文地址:Spring AOP 实现读写分离 博客地址:http://www.extlight.com 一.前言 上一篇<MySQL 实现主从复制> 文章中介绍了 MySQL 主从复制的搭 ...

  7. Jqmobile Secha Ionic比较

    1. Jqmobile 轻量级框架,它的语言基于 jquery 语言容易上手,运行速度快,但是没有 MVC 多人协作 开发的概念,项目比较大后 代码不易维护     (中小项目  1-2 个人开发很适 ...

  8. oracle行跟踪(基于行跟踪的ROWDEPENDENCIES ORA_ROWSCN信息)

    在Oracle 10g中的引入了ORA_ROWSCN伪列新特性.基于此种伪列所提供的信息,我们可以方便地找出某个数据块或某一个行最近被修改的时间戳.在默认情况下,10g下表会以非行依赖性(NOROWD ...

  9. C#多线程编程之:异步方法调用

    异步方法 当一个线程调用方法后,直到方法执行完毕,线程才继续执行,这种方法被称为同步方法.然而,有些方法执行时间可能非常长,比如串口操作或访问网络,这样线程被阻塞,而无法响应用户的其他请求.这种情况通 ...

  10. vim自定义配置之nerdTree

    vimConfig/plugin/nerdTree-setting.vim let g:NERDTree_title="[NERDTree]" nmap <F2> :N ...