题目传送门
题目大意
给你一棵树,共n个结点,每个结点具有一个颜色,可以对结点进行染色和查询
共n-1条边,分N-1行分别包含两个整数u和v,表示v是u的父节点
然后有m次操作
若为染色操作则输入“T x k”
若为查询操作则输入“C x”
思路
首先可以用dfs序将无根树区间化,即可以求出每个节点的管辖区间
然后就是区间修改,单点查询即可,维护每个点的值即可
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
#define debug(a) cout<<#a<<"="<<a<<endl;
#define INF 0x3f3f3f3f
const int N=5e4 +9;
int T, n, u, v, m, x, y, res;
int lid[N], rid[N], vis[N];
char op;
vector<int>g[N];
struct segtree{
int v, lazy;
}tr[N<<2];
inline void dfs(int v){
lid[v]=++res;
for(auto u:g[v]) dfs(u);
rid[v]=res;
}
inline int lc(int p) {return p<<1;}
inline int rc(int p) {return p<<1|1;}
inline void build(int p, int l, int r){
tr[p].v=-1;
tr[p].lazy=0;
if(l==r) return ;
int mid=(l+r)>>1;
build(lc(p), l, mid);
build(rc(p), mid+1, r);
}
inline void f(int p, int k){
tr[p].v=k;
tr[p].lazy=k;
}
inline void push_down(int p){
f(lc(p), tr[p].lazy);
f(rc(p), tr[p].lazy);
tr[p].lazy=0;
}
inline void updata(int p, int l, int r, int x, int y, int k){
if(x>r || y<l) return ;
if(l<=x && y<=r){
tr[p].v=k;
tr[p].lazy=k;
return ;
}
if(tr[p].lazy) push_down(p);
int mid=(x+y)>>1;
updata(lc(p), l, r, x, mid, k);
updata(rc(p), l, r, mid+1, y, k);
}
inline int query(int p, int d, int x, int y){
if(x==y) return tr[p].v;
if(tr[p].lazy) push_down(p);
int mid=(x+y)>>1;
if(d<=mid) return query(lc(p), d, x, mid);
else return query(rc(p), d, mid+1, y);
}
signed main(){
cin>>T;
int count=0;
while(T--){
cin>>n;
build(1,1,n);
for(int i=1; i<=n; i++) g[i].clear(), vis[i]=0;
res=0;
for(int i=1; i<=n-1; i++){
cin>>u>>v;
g[v].push_back(u);
vis[u]=1;
}
for(int i=1; i<=n; i++) if(!vis[i]) dfs(i);
cin>>m;
printf("Case #%d:\n", ++count);
for(int i=1; i<=m; i++){
cin>>op;
if(op=='C'){
cin>>x;
cout<<query(1,lid[x],1,n)<<endl;
}
else if(op=='T'){
cin>>x>>y;
updata(1,lid[x],rid[x],1,n,y);
}
}
}
return 0;
}