错误总结:
这一题没有1A,主要原因是有点累,在敲代码的过程中注意力有些无法集中起来。
最后导致在调用函数的地方传参数传错了!!!检查的时候只把函数认真看了一遍,而调用函数的地方却漏看了!!!!以后要注意!
题目大意:
给一个有根数,然后有以下两种操作。
操作一:T X Y ,将以X为根的子树上的所有节点都变成Y
操作二:C X,查询第X号点是多少?
这一题初看是一道维护树型结构的题,但它更新的是整颗子树的值,所以可以转化成DFS序后用线段树来维护。
具体如下:
一开始给定了这样一棵树
2
/ \
3 5
/ \
4 1
转化成DFS序:2344113552(这个可以DFS求出)
然后记录下每个数字最左边和最右边的位置,如:left[3] = 2, right[3] = 7。
因为DFS序的性质,x的所有子节点i,都满足left[i]∈[left[x], right[x]] 和 right[i]∈[left[x], right[x]]
所以操作一和操作二就可以转换到DFS序上进行。
操作一:
updata(p_left[x], p_right[x], 1, val, i);
操作二:
query(p_left[x], 1);
这一题就变成了。区间赋值修改和单点查询,所以考虑使用线段树来维护。
(这一题好像只要直接做用最简单线段树维护就好了,即如果能够包含整段节点区间就直接更新这个节点的值,否则就将该节点的值传递到他的左右子节点,然后递归到左右子节点进行操作。。。一开始脑抽了,以为会退化以至于超时。。。。)
所以我才用了别的方法。
我在每个线段树节点中除了有一个num值记录改节点的值,还有一个time值记录该节点的值是在第几次操作中被修改的。
class node
{
public:
int x, y, num, time;
};
所以这样就不需要考虑把节点的值传递给其左右自由节点。只要直接维护线段树的Num和time值就好了。
void updata(int x, int y, int t, int val, int time)
{
if (a[t].x > y || a[t].y < x)
return;
if (x <= a[t].x && a[t].y <= y)
{
a[t].num = val;
a[t].time = time;
return;
}
updata(x, y, t*2, val, time);
updata(x, y, t*2+1, val, time);
}
然后查询的时候就输出,所有包含x的节点中time值最大的那个节点的num值(好绕。。。。)
void query(int pos, int t)
{
if (pos > a[t].y || pos < a[t].x)
return;
if (a[t].time > ans_time)
{
ans_time = a[t].time;
ans = a[t].num;
}
if (a[t].x != a[t].y)
{
query(pos, t*2);
query(pos, t*2+1);
}
return;
}
最后贴上我的全部代码:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace std;
class node
{
public:
int x, y, num, time;
};
const int MAXN = 6e4;
vector <int> v[MAXN];
int pos[MAXN*2], p_left[MAXN], p_right[MAXN];
node a[5*MAXN];
int n, index, m, ans, ans_time;
void build(int x, int y, int t)
{
int mid;
a[t].x = x;
a[t].y = y;
a[t].time = 0;
a[t].num = -1;
if (x != y)
{
mid = (x + y) / 2;
build(x, mid, t*2);
build(mid+1, y, t*2+1);
}
return;
}
void query(int pos, int t)
{
if (pos > a[t].y || pos < a[t].x)
return;
if (a[t].time > ans_time)
{
ans_time = a[t].time;
ans = a[t].num;
}
if (a[t].x != a[t].y)
{
query(pos, t*2);
query(pos, t*2+1);
}
return;
}
void updata(int x, int y, int t, int val, int time)
{
if (a[t].x > y || a[t].y < x)
return;
if (x <= a[t].x && a[t].y <= y)
{
a[t].num = val;
a[t].time = time;
return;
}
updata(x, y, t*2, val, time);
updata(x, y, t*2+1, val, time);
}
void dfs(int x)
{
int i;
index ++;
pos[index] = x;
p_left[x] = index;
for (i=0; i<v[x].size(); i++)
dfs(v[x][i]);
index ++;
pos[index] = x;
p_right[x] = index;
return;
}
int main()
{
int T, tt, i, x, y, root, val;
char c;
scanf("%d",&T);
tt = 0;
while (T--)
{
tt++;
scanf("%d",&n);
root = 0;
for (i = 1; i <= n; i++)
{
v[i].clear();
root = root ^ i;
}
for (i = 1; i < n; i ++)
{
scanf("%d%d",&x,&y);
v[y].push_back(x);
root = root ^ x;
}
index = 0;
dfs(root);
build(1, 2*n, 1);
printf("Case #%d:\n", tt);
scanf("%d",&m);
for (i=1; i<=m; i++)
{
scanf("%c",&c);
while (c != 'T' && c != 'C')
scanf("%c",&c);
// cout << c << endl;
if (c == 'C')
{
scanf("%d",&x);
ans_time = 0;
ans = -1;
query(p_left[x], 1);
printf("%d\n", ans);
}
else if (c == 'T')
{
scanf("%d%d",&x,&val);
// cout << p_left[x] << ' ' << p_right[x] << endl;
updata(p_left[x], p_right[x], 1, val, i);
}
}
}
return 0;
}