hdu3974
题目是给定一棵树,然后一种操作是指定一个点,这个点及这个点的的子树被染色,另一种操作是指定一个点,问这个点的颜色.
可以通过dfs树将这棵树放在线段上,记结点u在线段上的位置是pos[u],以结点u为根的子树的结点总数是cnt[u],那么在每次染色就是染色线段上pos[u]~pos[u]+cnt[u]-1这段区间.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<set>
#include<stack>
using namespace std;
const int maxn=50005;
vector<int> adj[maxn];
int cnt[maxn],pos[maxn],c[maxn<<2];
bool vis[maxn];
int n,m;
int dfs(int u)
{
pos[u]=++m;
int res=1;
for(int i=0;i<adj[u].size();i++){
int v=adj[u][i];
if(vis[v])continue;
vis[v]=true;
res+=dfs(v);
}
return cnt[u]=res;
}
void pushdown(int m)
{
if(c[m]==-1)return ;
c[m<<1]=c[m<<1|1]=c[m];
c[m]=-1;
return ;
}
void update(int m,int s,int e,int l,int r,int p)
{
if(s>=l&&e<=r){
c[m]=p;
return ;
}
pushdown(m);
int mid=(s+e)>>1;
if(l<=mid)
update(m<<1,s,mid,l,r,p);
if(r>mid)
update(m<<1|1,mid+1,e,l,r,p);
//return ;
}
int query(int m,int l,int r,int p)
{
if(l==r){
return c[m];
}
pushdown(m);
int mid=(l+r)>>1;
if(p<=mid)
return query(m<<1,l,mid,p);
else{
return query(m<<1|1,mid+1,r,p);
}
}
int main()
{
int t,C=1;
scanf("%d",&t);
while(t--){
printf("Case #%d:\n",C++);
scanf("%d",&n);
for(int i=1;i<=n;i++){
adj[i].clear();
}
memset(cnt,0,sizeof(cnt));
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
adj[v].push_back(u);
cnt[u]++;
}
for(int i=1;i<=n;i++){
if(!cnt[i]){
memset(cnt,0,sizeof(cnt));
memset(vis,false,sizeof(vis));
m=0;
dfs(i);
break;
}
}
memset(c,-1,sizeof(c));
int q;
char op[3];
scanf("%d",&q);
while(q--){
scanf("%s",&op);
if(op[0]=='C'){
int pre;
scanf("%d",&pre);
//printf("%c %d\n",op[0],pre);
printf("%d\n",query(1,1,n,pos[pre]));
}
else{
int x,y;
scanf("%d%d",&x,&y);
update(1,1,n,pos[x],pos[x]+cnt[x]-1,y);
//printf("%c %d %d\n",op[0],l,r);
}
}
}
return 0;
}