题目链接:题目传送门
题目大意:
现有一棵树,有以下操作:
- 节点x及其所有子孙颜色都变更为k。
- 要求你回答节点x的颜色。
初始所有点都没有染色。
Input
第一行一个整数T(T <= 10),表示样例组数。
对于每个测试样例:
第一行一个整数n(n <= 5e4),表示树的节点个数。
接下来n行,每行两个整数u, v(1 <= u, v <= n),表示树中u的父节点是v。
接下来一行一个整数q(q <= 5e4),表示询问数。
接下来q行:
若为染色操作则输入“T x k”,若为查询操作则输入“C x”,(1 <= x <= n, 0 <= y <= 1e9)。
Output
每个测试样例首先输出一行"Case #x:",其中x为当前样例编号。
对于每个询问操作输出一个整数,表示当前节点的颜色,若还未染色则输出-1。
Sample Input
1
5
4 3
3 2
1 3
5 2
5
C 3
T 2 1
C 3
T 3 2
C 3
Sample Output
Case #1:
-1
1
2
思路:
一看是树形结构,不是dfs序就是并查集,dfs需要和线段树以及时间戳结合,因此并查集简单些,但是这里不能用路劲压缩(我就错在这里),**因为路径压缩找的时根节点不是父子节点,**看代码。
代码:
#include<iostream>
#include<set>
#include<vector>
#include<queue>
#include<string.h>
#include<algorithm>
#include<stack>
#include<map>
using namespace std;
typedef long long int ll;
const ll N = 5e4 + 100;
ll color[N],f[N],time[N];
int main()
{
ios::sync_with_stdio(false);
int t,n;
cin>>t;
int flag=0;
while(t--)
{
flag++;
cin>>n;
for(int i=1;i<=n;i++)
{
f[i]=i;
color[i]=-1;
time[i]=-1;
}
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
f[x]=y;//记录父子关系
}
int q,cnt=0;
cin>>q;
cout<<"Case #"<<flag<<":"<<'\n';
while(q--)
{
char p;
int x,y;
cin>>p;
if(p=='C')
{
cin>>x;
int cnr=x,ans=color[cnr],lastt=-1;
while(cnr!=f[cnr])
{
if(time[cnr]>lastt)//证明在这个点被改变颜色了,改变的更晚些
{
lastt=time[cnr];
ans=color[cnr];
}
cnr=f[cnr];//父子节点,向上寻找
}
if(time[cnr]>lastt)
{
lastt=time[cnr];
ans=color[cnr];
}//再判断下 ,因为最上面的根节点也可能改变颜色了
cout<<ans<<'\n';
}
else if(p=='T')
{
cin>>x>>y;
color[x]=y;
time[x]=cnt++;
}
}
}
return 0;
}