题目链接

题目翻译(摘自洛谷)

疯狂科学家Mike培养了一颗有根树,由n个节点组成。每个节点是一个要么装满水要么为空的贮水容器. 树的节点用1~n编号,其中根节点为1.对于每个节点的容器,其子节点的容器均在这一容器下方,并且每个节点都由一根可以向下流水的管道与其子节点连接. Mike想要对这棵树做以下操作:
1将节点v注满水. 这样v和其子节点都会充满水.
2将节点v置空. 这样v及其祖先节点(从v到根节点的路径)都会被置空.
3查询当前节点v是否充满水.
初始时,所有节点都为空. Mike已经制定好了他的操作顺序. 在对树进行实验前,他决定先模拟一下操作. 请你帮助Mike得出他操作后的结果.

思路

裸树链剖分,区间修改,单点查询。

 #include<iostream>
#include<cstdio>
using namespace std;
const int N=;
int n,cnt,dcnt,hd[N];
struct edge
{
int to,nxt;
}v[*N];
struct node
{
int fa,son,sz,dep,tp,s,e;
}tr[N];
struct segtree
{
int l,r,stat,tag;
}st[*N];
void addedge(int x,int y)
{
v[++cnt].to=y;
v[cnt].nxt=hd[x];
hd[x]=cnt;
}
void dfs1(int u)
{
tr[u].sz=;
for(int i=hd[u];i;i=v[i].nxt)
if(v[i].to!=tr[u].fa)
{
tr[v[i].to].fa=u;
tr[v[i].to].dep=tr[u].dep+;
dfs1(v[i].to);
tr[u].sz+=tr[v[i].to].sz;
if(tr[v[i].to].sz>tr[tr[u].son].sz)
tr[u].son=v[i].to;
}
}
void dfs2(int u,int top)
{
tr[u].tp=top;
tr[u].s=++dcnt;
if(tr[u].son)
{
dfs2(tr[u].son,top);
for(int i=hd[u];i;i=v[i].nxt)
if(v[i].to!=tr[u].fa&&v[i].to!=tr[u].son)
dfs2(v[i].to,v[i].to);
}
tr[u].e=dcnt;
}
void build(int num,int l,int r)
{
st[num].l=l,st[num].r=r;
st[num].tag=-;
if(l==r)
return ;
int mid=(l+r)/;
build(*num,l,mid),build(*num+,mid+,r);
}
void pushdown(int num)
{
if(st[num].tag!=-)
{
if(st[num].l!=st[num].r)
{
st[*num].stat=st[*num+].stat=st[num].tag;
st[*num].tag=st[*num+].tag=st[num].tag;
}
st[num].tag=-;
}
}
void change(int num,int l,int r,int z)
{
if(l>st[num].r||r<st[num].l)
return ;
if(st[num].l>=l&&st[num].r<=r)
{
st[num].tag=st[num].stat=z;
return ;
}
pushdown(num);
change(*num,l,r,z),change(*num+,l,r,z);
}
int query(int num,int x)
{
if(st[num].l>x||st[num].r<x)
return ;
if(st[num].l==st[num].r)
return st[num].stat;
pushdown(num);
return query(*num,x)+query(*num+,x);
}
void fnd(int x)
{
int f1=tr[x].tp;
while(f1!=)
{
change(,tr[f1].s,tr[x].s,);
x=tr[f1].fa,f1=tr[x].tp;
}
change(,,tr[x].s,);
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n-;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y),addedge(y,x);
}
dfs1();
dfs2(,);
build(,,n);
int q,x,y;
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&x,&y);
switch(x)
{
case :
change(,tr[y].s,tr[y].e,);
break;
case :
fnd(y);
break;
case :
printf("%d\n",query(,tr[y].s));
break;
}
}
return ;
}

最新文章

  1. EasyPR--开发详解(4)形态学操作、尺寸验证、旋转等操作
  2. jedis池的作用
  3. golang os/exec 执行外部命令
  4. 怎么在excel中快速查找重复记录
  5. Nexus Repository Manager 3.0 发布
  6. iOS事件传递&amp;响应者链条
  7. SharpMap V1.1 For Web教程系列之——前言
  8. JAVA泛型-自动包装机制不能应用于泛型数据的测试
  9. HTML语言笔记
  10. 规范的python编码
  11. email program (客户端)演变过程有感
  12. AHOI2013 差异 【后缀数组】
  13. gethostbyname和gethostbyaddr
  14. k-近邻算法-优化约会网站的配对效果
  15. Spring-Cloud-Gateway 从升级到放弃
  16. 【转】Gulp入门基础教程
  17. 教你如何在linux下查看服务是否已经启动或者关闭
  18. debug阶段贡献分
  19. spring mvc json的输入输出
  20. Nginx动静分离知识及配置

热门文章

  1. Linux并发与同步专题 (1)原子操作和内存屏障
  2. PHP之基本操作
  3. C#_IO操作_查询指定文件夹下的每个子文件夹占空间的大小
  4. flex布局,最后一行左对齐
  5. Mysql MHA高可用集群架构
  6. HAAR与DLib的实时人脸检测之实现与对比
  7. jQuery 初识 筛选器 属性选择器
  8. hdu 2063 给男女匹配 (匈牙利算法)
  9. Python_内置函数之round的幺蛾子
  10. Vue父子传值