题意

给定一棵以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. Alpha阶段贡献分配规则

    作业要求[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2244] 分配规则: 1.每人有基础分3分. 2.每参加一次组内会议及活动加0. ...

  2. 关于React setState的实现原理(一)

    前言 首先在学习react的时候就对setSate的实现有比较浓厚的兴趣,那么对于下边的代码,可以快速回答吗? class Root extends React.Component { constru ...

  3. php http build query

    http_build_query (PHP 5, PHP 7) http_build_query — 生成 URL-encode 之后的请求字符串 说明¶ string http_build_quer ...

  4. python3 读入一个jpg格式的图片,并转换长宽像素个数,然后进行绘制

    import matplotlib.pyplot as plt from scipy import ndimage import numpy as np import scipy fname=&quo ...

  5. 树的直径证明+HDU2196

    首先把无向图变成一棵树,直径肯定由叶子组成. 有以下两种情况: 第一种:经过根节点,则找两个最远的叶子肯定是直径,也就是B+D. 第二种:不经过根节点,则目标的两个叶子肯定有一个不为根的公共祖先,如红 ...

  6. scanf()与gets()的区别

    scanf()与gets()的区别 1.scanf()可以同时接受多个字符串,而gets()一次只能接受一个字符串. #include<stdio.h>int main(){ char s ...

  7. Yarn import now uses package-lock.json

    转发自: https://yarnpkg.com/blog/2018/06/04/yarn-import-package-lock/?utm_source=tuicool&utm_medium ...

  8. vs2013突然没有代码提示功能了。

    工具->选项->文本编辑器->C++ ->高级->禁用IntelliSense设置 false 然后选确定.

  9. erlang单独配置文件

    一种是erl启动的时候加参数 doudizhu.config [ {doudizhu,[ {listen_port, }, {node_caller_prefix,"ruby"}, ...

  10. RPC框架之Thrift分析(转)

    一.简介 1.Thrift是Facebook开发的跨语言的RPC服务框架.随后贡献给Apache开源组织.成为RPC服务的主流框架.   2.特点:  优点:       跨语言,支持java.c/c ...