hdu3974 Assign the task (线段树 + 树形结构转为线性结构)

题目链接:hdu 3974

大意:给你一棵树,当你在某个结点修改地时候,那么以这个结点为根地子树地所有结点都会做一样的修改,我们可以把这个树转化为区间问题,按照dfs的方式去遍历这棵树,然后入栈的序列即这些结点转化为区间时在区间中的序号,因此每个结点所代表的子树相当于一段区间,我们要记录每个结点所对应的区间起点和区间终点。看代码即可理解!

代码:

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
#define maxn 50000+5

vector<int> vv[maxn];
int startt[maxn], endd[maxn];
int tree[maxn<<2];
int col[maxn<<2];
int cnt;
void turn_tree_line(int u)
{
	cnt++;
	startt[u] = cnt;
	for(int i = 0; i < vv[u].size(); i++){
		turn_tree_line(vv[u][i]);
	}
	endd[u] = cnt;
}
void build(int left, int right, int rt)
{
	tree[rt] = -1;	
	col[rt] = 0; 
	if(left == right) return ;
	int mid = (left + right)>>1;
	build(left, mid, rt<<1);
	build(mid + 1, right, (rt<<1)|1);
}
void pushDown(int rt)
{
	if(col[rt]){
		tree[rt<<1] = tree[(rt<<1)|1] = tree[rt];
		col[rt<<1] = col[(rt<<1)|1] = col[rt];
		col[rt] = 0;
	}
}
int query(int pos, int left, int right, int rt)
{
	if(left == right)
		return tree[rt];
	int mid = (left + right)>>1;
	pushDown(rt);
	if(pos <= mid) return query(pos, left, mid, rt<<1);
	else if(pos > mid) return query(pos, mid + 1, right, (rt<<1)|1);
}
void upDate(int l, int r, int c, int left, int right, int rt)
{
	if(l <= left && right <= r){
		tree[rt] = c;
		col[rt] = 1;
		return ;
	}
	pushDown(rt);
	int mid = (left + right)>>1;
	if(l <= mid) upDate(l, r, c, left, mid, rt<<1);
	if(r > mid) upDate(l, r, c, mid + 1, right, (rt<<1)|1);
}
int main()
{
	int t, n, m, a, b, cases = 1;
	scanf("%d", &t);
	while(t--){
		printf("Case #%d:\n", cases++);
		for(int i = 0; i < maxn; i++){
			vv[i].clear();
		} 
		cnt = 0;
		int dd[maxn];
		memset(dd, 0, sizeof(dd));
		scanf("%d", &n);
		build(1, n, 1);
		for(int i = 0; i < n - 1; i++){
			scanf("%d%d", &a, &b);
			vv[b].push_back(a);
			dd[a] = 1;
		}
		int u;
		for(int i = 1; i <= n; i++)
			if(dd[i] == 0) u = i;
		turn_tree_line(u);
		scanf("%d", &m);
		char ch[10]; int d, e;
		for(int i = 0; i < m; i++){
			scanf("%s", ch);
			if(ch[0] == 'C'){
				scanf("%d", &d);
				printf("%d\n", query(startt[d], 1, n, 1));
			}
			else if(ch[0] == 'T'){
				scanf("%d%d", &d, &e);
				upDate(startt[d], endd[d], e, 1, n, 1);
			}
		}
	}
	return 0;
}
/*
100
15
2 1
9 1
3 2
6 2
4 3
5 3
7 6
8 6
11 10
10 9
12 10
14 13
15 13
13 9
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值