题意

给定一棵以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. js base64 转成图片上传

    直接上代码,要点就是把base64转成Blob,添加到FormData传递给后台程序,跟选择图片文件上传时一样的了. var dataurl = canvas.toDataURL('image/png ...

  2. Java并发编程之三:volatile关键字解析 转载

    目录: <Java并发编程之三:volatile关键字解析 转载> <Synchronized之一:基本使用>   volatile这个关键字可能很多朋友都听说过,或许也都用过 ...

  3. 利用 Create React Native App 快速创建 React Native 应用

    本文介绍的 Create-React-Native-App 是非常 Awesome 的工具,而其背后的 Expo 整个平台也让笔者感觉非常的不错.笔者目前公司是采用 APICloud 进行移动应用开发 ...

  4. 《DSP using MATLAB》Problem 2.16

    先由脉冲响应序列h(n)得到差分方程系数,过程如下: 代码: %% ------------------------------------------------------------------ ...

  5. 《DSP using MATLAB》示例Example 10.4

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  6. BZOJ1233 [Usaco2009Open]干草堆tower 和 BZOJ3549 [ONTAK2010]Tower

    题意 Problem 3549. -- [ONTAK2010]Tower 3549: [ONTAK2010]Tower Time Limit: 10 Sec  Memory Limit: 64 MBS ...

  7. maven打jar到私服

    <dependency> <groupId>fakepath</groupId> <artifactId>wcs-java-sdk</artifa ...

  8. 基于ffmpegSDK的开发

    #include <stdio.h> #include <libavutil/avutil.h> #include <libavcodec/avcodec.h> # ...

  9. sql server获取插入记录后的ID

    select @@IDENTITY --返回为当前会话的所有作用域中的任何表最后生成的标识值. select IDENT_CURRENT('table_name') --返回为任何会话和任何作用域中的 ...

  10. 【转】Java 字节流与字符流的区别

    字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢?实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作 ...