链接 water tree
题意:
给一颗树,初始节点值为 0 ,三个操作
- 将 x 的子树节点值变成 1.
- 将 x 的父节点值变成 0.
- 查询 x 节点的值。
思路:
树链剖分模板,1 2 操作分别对应 子树修改 和 链修改 (1-x),3操作为单点查询。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll ;
const int maxn=1e6+7;
ll sum[maxn<<2],lazy[maxn<<2],val[maxn],p,n,m;
int depth[maxn],siz[maxn],fa[maxn],son[maxn],cnt,id[maxn],tot[maxn],num,head[maxn<<1];
struct node{
int u,v,next;
}e[maxn<<1];
void add(int u,int v){
e[++num].next=head[u];
e[num].v=v;
head[u]=num;
}
void dfs1(int u,int pre,int dep){
depth[u]=dep; siz[u]=1; fa[u]=pre;
for(int i=head[u]; i; i=e[i].next){
int to = e[i].v;
if( to == pre) continue;
dfs1(to,u,dep+1);
siz[u]+=siz[to];
if(siz[to]>siz[son[u]]) son[u]=to; //更新重儿子
}
}
void dfs2(int u,int t){
id[u]=++cnt; //赋予新的序列号
tot[u]=t; //重边顶点
if(son[u]) dfs2(son[u],t); //优先对重链编号
for(int i=head[u];i;i=e[i].next){
int to=e[i].v;
if(to!=son[u]&&to!=fa[u]) //跳过重儿子和父节点
dfs2(to,to); //非重儿子的 tot是本身
}
}
void pushdown(int rt,int l,int r){
int m=(l+r)>>1;
if(lazy[rt]!=-1){
lazy[rt<<1]=lazy[rt];
lazy[rt<<1|1]=lazy[rt];
sum[rt<<1]=lazy[rt];
sum[rt<<1|1]=lazy[rt];
lazy[rt]=-1;
}
}
void build(int l,int r,int rt){
if(l==r){
lazy[rt]=-1;
sum[rt]=0;
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
void update(int x,int y,int v,int l,int r,int rt){
if(x<=l&&y>=r){
lazy[rt]=v;
sum[rt]=v;
return ;
}
pushdown(rt,l,r);
int m=(l+r)>>1;
if(x<=m) update(x,y,v,l,m,rt<<1);
if(y>m) update(x,y,v,m+1,r,rt<<1|1);
}
ll query(int id,int l,int r,int rt){
ll s=0;
if(l==r){
return sum[rt];
}
pushdown(rt,l,r);
int m=(l+r)>>1;
if(id<=m) return query(id,l,m,rt<<1);
if(id>m) return query(id,m+1,r,rt<<1|1);
}
void add_v(int x,int y,int v){
while(tot[x]!=tot[y]){
if(depth [tot[x]]< depth[tot[y]]) swap(x,y);
update( id [tot[x]],id[x],v,1,n,1);
x=fa[tot[x]];
}
if(depth[x]>depth[y]) swap(x,y);
update(id[x],id[y],v,1,n,1);
}
int main (){
cin>>n;
for(int i=0,u,v;i<n-1;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(1,-1,0);dfs2(1,1);
build(1,n,1);
cin>>m;
for(int i=0;i<m;i++){
int t,x;
scanf("%d%d",&t,&x);
if(t==2) add_v(1,x,0);
if(t==1) update(id[x],id[x]+siz[x]-1,1,1,n,1);
if(t==3) printf ("%d\n",query(id[x],1,n,1));
}
}