题意:有一棵树,最开始每个节点权值都为-1,有两种操作,第一种查询当前节点的权值,第二种更改以当前节点为根的子树的所有点的权值。
思路:线段树+dfs序维护,据说这是线段树基本操作(瑟瑟发抖)
#include<bits/stdc++.h>
#define read(x) scanf("%d",&x)
#define debug puts("###")
using namespace std;
const int maxn=5e5+10;
int task[maxn<<2],la[maxn<<2];
struct node{
int to,next;
}edge[maxn];
int l1,l[maxn],r[maxn];
int use[maxn],head[maxn],num;
void addedge(int u,int v) {
edge[l1].to=u;
edge[l1].next=head[v];
head[v]=l1++;
}
void dfs(int rt) {
int i=head[rt];
l[rt]=++num;
while(i!=-1) {
dfs(edge[i].to);
i=edge[i].next;
}
r[rt]=num;
}
void push(int rt) {
if(la[rt]!=-1) {
task[rt<<1]=la[rt];
task[rt<<1|1]=la[rt];
la[rt<<1]=la[rt];
la[rt<<1|1]=la[rt];
la[rt]=-1;
}
}
int find_set(int x) {
if(use[x] != x) {
use[x]=find_set(use[x]);
}
return use[x];
}
void build(int l,int r,int rt) {
task[rt]=-1;
la[rt]=-1;
if(l==r) return ;
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
void update(int L,int R,int val,int l,int r,int rt) {
if(L <= l && r <= R) {
task[rt]=val;
la[rt]=val;
return;
}
push(rt);
int m=(l+r)>>1;
if(L <= m) update(L,R,val,l,m,rt<<1);
if(R > m) update(L,R,val,m+1,r,rt<<1|1);
}
void query(int L,int R,int l,int r,int rt) {
if(L <= l && r <= R) {
printf("%d\n",task[rt]);
return;
}
push(rt);
int m=(l+r)>>1;
if(L <= m) query(L,R,l,m,rt<<1);
if(R > m) query(L,R,m+1,r,rt<<1|1);
}
int main() {
int T;
scanf("%d",&T);
int cas=1;
while(T--) {
int n;
scanf("%d",&n);
l1=0;
num=0;
for(int i=0;i<=n;i++) {
head[i]=-1;
use[i]=i;
}
int u,v;
for(int i=1;i<n;i++) {
scanf("%d%d",&u,&v);
use[u]=v;
addedge(u,v);
}
int root=find_set(1);
dfs(root);
build(1,num,1);
int m;
read(m);
char op[5];
int a,b;
printf("Case #%d:\n",cas++);
for(int i=0;i<m;i++) {
scanf("%s",op);
if(op[0]=='C') {
read(a);
query(l[a],l[a],1,num,1);
}
else {
read(a),read(b);
update(l[a],r[a],b,1,num,1);
}
}
}
}