传送门
http://codeforces.com/problemset/problem/343/D
题目大意
给定一棵树,要求支持如下操作
1.对于a的子树全部赋值为1
2.对于a到根的路径上的点都赋值为0
3.单点查询
题解
路径修改+子树修改+单点查询依照我数据结构总结里的子树修改+单点查询和路径修改+单点查询即可完成
但是,还存在有两个问题
1.子树修改转区间修改时的标记下放
2.子树中某点打完贡献标记后,要对子树中的某个子树执行操作1,他的贡献标记怎么处理
我们维护3个域
1.点权值
2.贡献标记
3.区间变1标记
操作1:查询a的子树中有没有贡献标记,如果有且a有父节点,那么对a的父节点打上贡献标记,然后区间修改,点的权值为0,贡献标记取消
操作2:单点修改a的贡献标记
操作3:先查询a子树的贡献标记,如果有,输出0,如果没有输出a的单点权值
以上需要支持:修改区间为0+修改单点贡献标记+查询子树的贡献标记+查询单点权值
const
maxn=500005;
var
w:array[0..4*maxn,1..5]of longint;
x:array[0..4*maxn,1..2]of longint;
y:array[0..maxn,1..2]of longint;
fa:array[0..maxn]of longint;
i,j,k:longint;
n,m,a,b,len,tt:longint;
procedure init(a,b:longint);
begin
x[len,1]:=b;
if x[a,2]=0
then x[a,2]:=len else x[x[a,1],2]:=len;
x[a,1]:=len; inc(len);
end;
procedure dfs(a:longint);
var tt:longint;
begin
inc(len); y[a,1]:=len; tt:=x[a,2];
while tt<>0 do
begin
if y[x[tt,1],1]=0 then begin fa[x[tt,1]]:=a; dfs(x[tt,1]); end;
tt:=x[tt,2];
end;
y[a,2]:=len;
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r; w[a,3]:=0; w[a,4]:=0; w[a,5]:=-1;
if l=r then exit;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;
procedure pushdown(a:longint);
begin
if w[a,1]=w[a,2] then begin w[a,5]:=-1; exit; end;
w[a<<1,3]:=1; w[a<<1,4]:=0; w[a<<1,5]:=1; w[a<<1+1,3]:=1; w[a<<1+1,4]:=0; w[a<<1+1,5]:=1;
w[a,5]:=-1;
end;
function query1(a,l,r:longint):longint;
var mid:longint;
begin
if w[a,5]<>-1 then pushdown(a);
if (l=w[a,1])and(r=w[a,2]) then exit(w[a,4]);
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then exit(query1(a<<1,l,r)) else
if l>mid then exit(query1(a<<1+1,l,r))
else exit(query1(a<<1,l,mid)or query1(a<<1+1,mid+1,r));
end;
function query2(a,b:longint):longint;
var mid:longint;
begin
if w[a,5]<>-1 then pushdown(a);
if (w[a,1]=w[a,2])and(w[a,1]=b) then exit(w[a,3]);
mid:=(w[a,1]+w[a,2])>>1;
if b<=mid then exit(query2(a<<1,b)) else exit(query2(a<<1+1,b));
end;
procedure update1(a,b:longint);
var mid:longint;
begin
if w[a,5]<>-1 then pushdown(a);
if (w[a,1]=w[a,2])and(w[a,1]=b) then begin w[a,4]:=1; exit; end;
mid:=(w[a,1]+w[a,2])>>1;
if b<=mid then update1(a<<1,b) else update1(a<<1+1,b);
w[a,4]:=w[a<<1,4] or w[a<<1+1,4];
end;
procedure update2(a,l,r:longint);
var mid:longint;
begin
if w[a,5]<>-1 then pushdown(a);
if (w[a,1]=l)and(w[a,2]=r) then begin w[a,3]:=1; w[a,4]:=0; w[a,5]:=1; exit; end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then update2(a<<1,l,r) else
if l>mid then update2(a<<1+1,l,r)
else begin update2(a<<1,l,mid); update2(a<<1+1,mid+1,r); end;
w[a,4]:=w[a<<1,4] or w[a<<1+1,4];
end;
begin
readln(n); len:=n+1;
for i:=1 to n-1 do
begin
readln(a,b); init(a,b); init(b,a);
end;
len:=0; dfs(1);
build(1,1,n);
readln(m);
for i:=1 to m do
begin
readln(a,b);
case a of
1:begin
tt:=query1(1,y[b,1],y[b,2]);
if (tt=1)and(fa[b]<>0) then update1(1,y[fa[b],1]);
update2(1,y[b,1],y[b,2]); {writeln(tt);}
end;
2:begin update1(1,y[b,1]); end;
3:begin
tt:=query1(1,y[b,1],y[b,2]);
if tt=1 then writeln(0) else writeln(query2(1,y[b,1]));
end;
end;
end;
end.