hdu3974

这题已经确定了思路了,寻找区间,只是我在做的时候是通过记录各个节点的子结点的个数,而别人是直接通过dfs序来求,后者要好

#include <bits/stdc++.h>
using namespace std;

const int N = 50050;

vector <int> boss[N], employee[N];
int L[N * 4], R[N * 4];

int n, q, cnt;
int s[N * 4], e[N * 4];
int task[N * 4];

void init(){
	for(int i = 0; i <= n; i ++){
		boss[i]. clear();
		employee[i]. clear();
	}
}
void dfs(int u){
	cnt ++;
	L[u] = cnt;
	for(int i = 0; i < boss[u]. size(); i ++){
		int v = boss[u][i];
		dfs(v);
	}
	R[u] = cnt;
}
void pushdown(int o, int num){
	if(task[o] != -1){
		task[o << 1] = task[o << 1 | 1] = task[o];
		task[o] = -1;
	}
}
void build(int l, int r, int o){
	s[o] = l;
	e[o] = r;
	task[o] = -1;
	if(l != r){
		int m = (l + r) >> 1;
		build(l, m, o << 1);
		build(m + 1, r, o << 1 | 1);
	}
}
void update(int t, int l, int r, int o){
	if(s[o] == l && e[o] == r){
		task[o] = t;
		return ;
	}
	if(s[o] == e[o])
		return ;
	pushdown(o, e[o] - s[o] + 1);
	int m = (s[o] + e[o]) >> 1;
	if(r <= m)
		update(t, l, r, o << 1);
	else if(l > m)
		update(t, l, r, o << 1 | 1);
	else{
		update(t, l, m, o << 1);
		update(t, m + 1, r, o << 1 | 1);
	}
}
int query(int x, int o){
	if(s[o] == x && e[o] == x)
		return task[o];
	pushdown(o, e[o] - s[o] + 1);
	int m = (s[o] + e[o]) >> 1;
	if(x <= m)
		return query(x, o << 1);
	else
		return query(x, o << 1 | 1);
}
int main(){
	int T;
	scanf("%d", &T);
	for(int _ = 1; _ <= T; _ ++){
		scanf("%d", &n);
		init();
		int u, v;
		for(int i = 1; i < n; i ++){
			scanf("%d %d", &u, &v);
			boss[v]. push_back(u);
			employee[u]. push_back(v);
		}
		cnt = 0;
		for(int i = 1; i <= n; i ++)
			if(employee[i]. size() == 0){
				dfs(i);
				break;
			}
		build(1, cnt, 1);
		scanf("%d", &q);
		printf("Case #%d:\n", _);
		char op[5];
		int x, y;
		while(q --){
			scanf("%s", op);
			if(op[0] == 'C'){
				scanf("%d", &x);
				printf("%d\n", query(L[x], 1));
			}
			else if(op[0] == 'T'){
				scanf("%d %d", &x, &y);
				update(y, L[x], R[x], 1);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/82528820
今日推荐