大致题意
有一家公司有N个员工(从1到N),公司里每个员工都有一个直接的老板(除了整个公司的领导)。如果你是某人的直接老板,那个人就是你的下属,他的所有下属也都是你的下属。如果你是没有人的老板,那么你就没有下属,没有直接老板的员工就是整个公司的领导,也就是说N个员工构成了一棵树。公司通常把一些任务分配给一些员工来完成,当一项任务分配给某个人时,他/她会把它分配给他/她的所有下属,换句话说,这个人和他/她的所有下属在同一时间接受了一项任务。此外,每当员工收到一个任务,他/她将停止当前任务(如果他/她有),并开始新的任务。在公司将某些任务分配给某个员工后,编写一个程序来帮助找出某个员工当前的任务。
Input
第一行包含单个正整数T(T<=10),表示测试用例的数量。对于每个测试用例:第一行包含一个整数N(N≤50,000),它是雇员的数目。下面的N-1行分别包含两个整数u和v,这意味着雇员v是雇员u的直接老板(1<=u,v<=N)。下一行包含一个整数M(M≤50,000)。下面的M行分别包含一条消息,“Cx”表示对员工x的当前任务的查询,“Tx y”表示公司将任务y分配给员工x。(1<=x<=N,0<=y<=10^9)
思路
每次修改一颗子树,容易想到是dfs序,然后就变成了线段树区间赋值,单点查询的题目。一个小坑点,query的时候第x个员工在线段树中的节点是in[x],不要写成x。
代码
这里是有根树,强调了父子关系,建单向边就行。
贴一下dfs序建线段树的代码。
#include<bits/stdc++.h>
using namespace std;
#define maxn 50005
#define maxm 20006
#define ll long long int
#define INF 0x3f3f3f3f
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
#define mem(a) memset(a,0,sizeof(a))
#define sqr(x) (x*x)
#define inf (ll)2e18+1
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
int T,n,m,in[maxn],out[maxn],t[maxn<<2],laz[maxn<<2],tim,du[maxn];
struct node{int v,nxt;}ed[maxn];
int head[maxn],tot;
void add(int x,int y){ed[++tot]={y,head[x]};head[x]=tot;}
void dfs(int x){
in[x]=++tim;
for(int i=head[x];i;i=ed[i].nxt){
int v=ed[i].v;
dfs(v);
}
out[x]=tim;
}
void pushdown(int x){
t[x<<1]=t[x<<1|1]=laz[x<<1]=laz[x<<1|1]=laz[x];
laz[x]=-1;
}
void update(int x,int l,int r,int lp,int rp,int v){
if(r>l&&laz[x]!=-1)pushdown(x);
if(lp<=l&&r<=rp){
t[x]=laz[x]=v;
return ;
}
int mid=(l+r)>>1;
if(lp<=mid)update(x<<1,l,mid,lp,rp,v);
if(mid+1<=rp)update(x<<1|1,mid+1,r,lp,rp,v);
}
int query(int x,int l,int r,int pos){
if(r>l&&laz[x]!=-1)pushdown(x);
if(l==r)return t[x];
int mid=(l+r)>>1;
if(pos<=mid)return query(x<<1,l,mid,pos);
else return query(x<<1|1,mid+1,r,pos);
}
int main()
{
int kase=0;
T=read();
while(T--){
printf("Case #%d:\n",++kase);
memset(laz,-1,sizeof(laz));
memset(t,-1,sizeof(t));
mem(head);mem(du);
tot=tim=0;
n=read();
int x,y,rt;char s[2];
inc(i,1,n-1){
x=read();y=read();
add(y,x);du[x]++;
}
inc(i,1,n)if(du[i]==0)rt=i;
dfs(rt);
m=read();
while(m--){
scanf("%s",s);
if(s[0]=='C'){
x=read();
printf("%d\n",query(1,1,n,in[x]));///注意这里查询点x的时候 对应的线段树中的点是in[x]...
}
else {
x=read();y=read();
update(1,1,n,in[x],out[x],y);
}
}
}
return 0;
}