【线段树】Hdu3974 Assign the task(dfs序建简单线段树)

题目:
公司里有从1到n共n个成员,除了董事长,每个人都有唯一一个直接上司。每个人都有若干下属,自己下属的下属仍然算作是自己的下属。当给某个成员分配工作时,该成员和其所有下属会立刻丢弃原来的工作,执行当前的工作。现在有两种操作(1)C x 查询成员x当前的工作内容(2)T x y为成员x分配新的任务y。对于每次查询操作输出相应的结果

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 5e4 + 10;
int t,m,n,a,b,c,q,k,cnt,u,v;
string str;
int tree[maxn<<2],ltree[maxn],rtree[maxn];//确定原来结点在线段树的区间
vector<int>pre[maxn];
bool vis[maxn];
void dfs(int pos){
	ltree[pos] = ++cnt;//区间左端点
	for(int i=0;i<pre[pos].size();i++){
		dfs(pre[pos][i]);
	}
	rtree[pos] = cnt;//区间右端点
}
void push_down(int rt){
	if(tree[rt] != -1){
		tree[rt<<1] = tree[rt<<1|1] = tree[rt];
		tree[rt] = -1;
	}
}
void update(int c,int l,int r,int rt){
	if(a<=l && b>=r){
		tree[rt] = c;
		return;
	}
	push_down(rt);
	int mid = (l+r)>>1;
	if(a<=mid) update(c,lson);
	if(b>mid) update(c,rson);
}
int query(int l,int r,int rt){
	if(l==r) return tree[rt];
	push_down(rt);
	int mid=(l+r) >> 1;
	if(a<=mid) query(lson);
	else query(rson);
}

int main(){
	cin>>t;
	for(int tt=1;tt<=t;tt++){
		memset(tree,-1,sizeof(tree));
	    memset(vis,0,sizeof(vis));
	    memset(ltree,-1,sizeof(ltree));
	    memset(rtree,-1,sizeof(rtree));
	    cnt = 0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) pre[i].clear();
		for(int i=1;i<=n-1;i++){
			scanf("%d%d",&u,&v);
			pre[v].push_back(u);
			vis[u] = 1;
		}
		for(int i=1;i<=n;i++){
			if(!vis[i]) dfs(i);
		}
		scanf("%d",&m);
		printf("Case #%d:\n",tt);
		while(m--){
			cin>>str;
			if(str[0] == 'C'){
				scanf("%d",&u);
				a=ltree[u];//左端点就是当前任务
				printf("%d\n",query(1,n<<1,1));
			}else{
				scanf("%d%d",&u,&v);
				a=ltree[u];
				b=rtree[u];
				update(v,1,n<<1,1);
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值