Generating Synergy bzoj-4154 Ipsc-2015

题目大意:给定一棵n个节点树,m个操作,支持:将一个点周围所有距该点距离不超过l的子结点的颜色改成另一种颜色;查询单点颜色。每个点的颜色开始都是1。

注释:$1\le n,m\le 10^5$


想法:这就是一个典型的不是KD-Tree裸题,我们需要将它转化成点。

首先,我们先拉出整棵树的dfs序。

每个节点,我们设横坐标就是dfs序上的下标,纵坐标就是深度。我们发现,一个点的子树是一段连续的区间,然后当深度确定是,我们发现这就是矩阵赋值,加上pushdown操作即可。

单点查询遍历即可。不要忘记query的时候也要pushdown

另外没有插入操作,就不用重构了。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
int head[N],to[N],nxt[N],cnt,deep[N],pos[N],last[N],tot,d,root;
struct data
{
int p[2],mx[2],mn[2],c[2],w,tag;
bool operator <(const data &a) const
{
return p[d]==a.p[d]?p[d^1]<a.p[d^1]:p[d]<a.p[d];
}
}a[N];
inline void add(int x,int y)
{
to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
}
void dfs(int x)
{
int i;
pos[x]=++tot,a[x].p[0]=pos[x],a[x].p[1]=deep[x];
for(i=head[x];i;i=nxt[i])
deep[to[i]]=deep[x]+1,dfs(to[i]);
last[x]=tot;
}
inline void pushup(int x)
{
int l=a[x].c[0],r=a[x].c[1];
a[x].mx[0]=max(a[x].p[0],max(a[l].mx[0],a[r].mx[0]));
a[x].mx[1]=max(a[x].p[1],max(a[l].mx[1],a[r].mx[1]));
a[x].mn[0]=min(a[x].p[0],min(a[l].mn[0],a[r].mn[0]));
a[x].mn[1]=min(a[x].p[1],min(a[l].mn[1],a[r].mn[1]));
}
int build(int l,int r,int now)
{
if(l>r) return 0;
int mid=(l+r)>>1;
d=now,nth_element(a+l,a+mid,a+r+1);
a[mid].w=1,a[mid].tag=0;
a[mid].c[0]=build(l,mid-1,now^1);
a[mid].c[1]=build(mid+1,r,now^1);
pushup(mid);
return mid;
}
inline void pushdown(int x)
{
if(a[x].tag)
{
int l=a[x].c[0],r=a[x].c[1];
a[l].w=a[l].tag=a[r].w=a[r].tag=a[x].tag;
a[x].tag=0;
}
}
void update(int bx,int ex,int by,int ey,int v,int x)
{
if(!x||a[x].mx[0]<bx||a[x].mn[0]>ex||a[x].mx[1]<by||a[x].mn[1]>ey)return;
if(a[x].mn[0]>=bx&&a[x].mx[0]<=ex&&a[x].mn[1]>=by&&a[x].mx[1]<=ey)
{
a[x].w=a[x].tag=v;
return;
}
pushdown(x);
if(a[x].p[0]>=bx&&a[x].p[0]<=ex&&a[x].p[1]>=by&&a[x].p[1]<=ey)a[x].w=v;
update(bx,ex,by,ey,v,a[x].c[0]),update(bx,ex,by,ey,v,a[x].c[1]);
}
int query(int px,int py,int x)
{
d^=1;
if(a[x].p[0]==px&&a[x].p[1]==py) return a[x].w;
pushdown(x);
if(d)
{
if(py<a[x].p[1]||(py==a[x].p[1]&&px<a[x].p[0])) return query(px,py,a[x].c[0]);
else return query(px,py,a[x].c[1]);
}
else
{
if(px<a[x].p[0]||(px==a[x].p[0]&&py<a[x].p[1])) return query(px,py,a[x].c[0]);
else return query(px,py,a[x].c[1]);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(head,0,sizeof(head)),cnt=1;
a[0].mx[0]=a[0].mx[1]=-1<<30,a[0].mn[0]=a[0].mn[1]=1<<30;
int n,m,i,x,y,z,ans=0;
scanf("%d%*d%d",&n,&m);
for(i=2;i<=n;i++) scanf("%d",&x),add(x,i);
dfs(1);
root=build(1,n,0);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
if(z) update(pos[x],last[x],deep[x],deep[x]+y,z,root);
else d=1,ans=(ans+(long long)query(pos[x],deep[x],root)*i)%1000000007;
}
printf("%d\n",ans);
}
return 0;
}

小结:KD-Tree这种题还是挺好玩的..

[bzoj4154][Ipsc2015]Generating Synergy_KD-Tree_dfs序的更多相关文章

  1. BZOJ4154: [Ipsc2015]Generating Synergy

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

  2. 【kd-tree】bzoj4154 [Ipsc2015]Generating Synergy

    区间修改的kd-tree,打标记,下传. 每次询问的时候,从询问点向上找到根,然后依次下传下来,再回答询问. #include<cstdio> #include<algorithm& ...

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

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

  4. 【BZOJ4154】[Ipsc2015]Generating Synergy KDtree

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

  5. BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree

    BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点 ...

  6. 【bzoj4154】[Ipsc2015]Generating Synergy KD-tree

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

  7. BZOJ 4154: [Ipsc2015]Generating Synergy KDtree+dfs序

    多组数据真tm恶心~ 把 $dfs$序和深度分别看作横纵坐标,然后用 $KDtree$ 数点就可以了~ #include <cstdio> #include <cstring> ...

  8. BZOJ4154:[IPSC2015]Generating Synergy

    浅谈\(K-D\) \(Tree\):https://www.cnblogs.com/AKMer/p/10387266.html 题目传送门:https://lydsy.com/JudgeOnline ...

  9. 【bzoj 4154】[Ipsc2015]Generating Synergy

    题目 大概已经掌握熟练码出\(kdt\)的技能了 发现距离子树根节点\(x\)不超过\(l\)的点可以用两种方式来限制,首先\(dfs\)序在\([dfn_x,dfn_x+sum_x)\)中,深度自然 ...

随机推荐

  1. PCB 录屏工具Screen2Exe GifCam ScreenToGif

    我们完成的软件作品后,需要向客户或领导演示软件功能介绍,这里力推3款录屏工具 一.Screen2Exe工具,录制exe视频文件 下载地址  http://pcbren.cn/ShareFiles/Sc ...

  2. [Apple开发者帐户帮助]八、管理档案(2)创建临时配置文件(iOS,tvOS,watchOS)

    创建临时配置文件以在设备上运行您的应用程序而无需Xcode.在开始之前,您需要一个App ID,一个分发证书和多个注册设备. 有关完整的临时配置文件工作流程,请转到Xcode帮助中的分发到已注册设备( ...

  3. Python/Django 下载Excel2003

    一.安装 目前支持Excel2003的第三方库多少还有几个,本文使用的是xlwt,安装方式命令行:pip install xlwt 二.使用 首先.引入该库,例如:from xlwt import * ...

  4. ios-判断手机上是否安装了某个App

    方法一     1.获取手机中安装的所有App   1.1.runtime中的方法,所以要导入       #include <objc/runtime.h>   1.2.在 AppDel ...

  5. android 二维码 扫描,生成,竖屏

    最近公司有用到二维码,生成,扫描,所以学习了一下,和大家分享: demo 见下面链接,已经改成竖屏: http://download.csdn.net/detail/q610098308/868101 ...

  6. C++ friend关键字

    友元:友元函数 友元类. 友元函数:不属于任何类,只是在类中声明一下(可以放在 private 或者 public,没有区别),告诉这个类,这个函数是你的朋友,当然朋友不是白当的:这个函数可以访问你的 ...

  7. 提高mysql千万级大数据SQL查询优化几条经验

    凯哥java                             微信号                             kaigejava 功能介绍                    ...

  8. c指针之内存释放

    // 1.正常使用包含指针的结构体 // 2.正常使用元素类型为指针的vector #include<string.h> #include<stdio.h> #include& ...

  9. 【技术累积】【点】【java】【25】Orderd

    基础概念 Orderd是spring core中定义的一个接口,使用它以及相关的Comparator和@Order注解,可以实现对元素的排序. @Order 直接先说下@Order注解吧,使用场景较多 ...

  10. C/C++ 之数组排序

    #include <stdio.h> #include <stdlib.h> void array_sort(int *a, int len) { int i, j, tmp; ...