描述
传送门:我是传送门
有一家公司有NN个员工(从1到N)(从1到N),公司里每个员工都有一个直接的老板(除了整个公司的领导)。如果你是某人的直接老板,那个人就是你的下属,他的所有下属也都是你的下属。如果你是没有人的老板,那么你就没有下属,没有直接老板的员工就是整个公司的领导,也就是说NN个员工构成了一棵树。公司通常把一些任务分配给一些员工来完成,当一项任务分配给某个人时,他/她会把它分配给他/她的所有下属,换句话说,这个人和他/她的所有下属在同一时间接受了一项任务。此外,每当员工收到一个任务,他/她将停止当前任务(如果他/她有),并开始新的任务。在公司将某些任务分配给某个员工后,编写一个程序来帮助找出某个员工当前的任务。
(直接贴中文题面,下边就不写题意了)
输入
第一行包含单个正整数T(T<=10)T(T<=10),表示测试用例的数量。对于每个测试用例:第一行包含一个整数N(N≤50,000)N(N≤50,000),它是雇员的数目。下面的N−1N−1行分别包含两个整数uu和vv,这意味着雇员v是雇员u的直接老板1<=u,v<=N)1<=u,v<=N)。下一行包含一个整数(M≤50,000)(M≤50,000)。下面的M行分别包含一条消息,“CxCx”表示对员工x的当前任务的查询,“TxyTxy”表示公司将任务yy分配给员工xx。(1<=x<=N,0<=y<=109)(1<=x<=N,0<=y<=109)
输出
对于每个测试用例,在第一行打印测试用例编号(以1开头),然后为每个查询输出相应的答案。
样例
输入
1
5
4 3
3 2
1 3
5 2
5
C 3
T 2 1
C 3
T 3 2
C 3
输出
Case #1:
-1
1
2
思路
学习了别人的代码才会写,CF马上开始了 下次补上代码中的注释以及自己对这道题的理解
代码
1 /* 2 * =========================================================== 3 * 4 * Filename: J.cpp 5 * 6 * Link: http://acm.hdu.edu.cn/showproblem.php?pid=3974 7 * 8 * Version: 1.0 9 * Created: 2018/09/15 17时29分26秒 10 * Revision: none 11 * Compiler: g++ 12 * 13 * Author: 杜宁元 (https://duny31030.top/), duny31030@126.com 14 * Organization: QLU_浪在ACM 15 * 16 * =========================================================== 17 */ 18 #include <bits/stdc++.h> 19 using namespace std; 20 #define clr(a, x) memset(a, x, sizeof(a)) 21 #define rep(i,a,n) for(int i=a;i<=n;i++) 22 #define pre(i,a,n) for(int i=n;i>=a;i--) 23 #define ll long long 24 #define max3(a,b,c) fmax(a,fmax(b,c)) 25 #define ios ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); 26 const double eps = 1e-6; 27 const int INF = 0x3f3f3f3f; 28 const int mod = 1e9 + 7; 29 const int MAXN = 5e4+100; 30 int T,N,M,u,v,x,y; 31 char op[10]; 32 33 vector<vector<int> > G; 34 int s[MAXN],e[MAXN],du[MAXN],Index; 35 36 void dfs(int u) 37 { 38 s[u] = ++Index; // 相当于是记录u的起始下属下标,结束下标在递归回来的时候确定的 39 int len = G[u].size(); 40 for(int i = 0;i < len;i++) 41 dfs(G[u][i]); 42 e[u] = Index; 43 } 44 45 struct node 46 { 47 int l,r; 48 int task,flag; // flag表示区间是否被全部覆盖,task表示此区间的工作室什么 49 }tree[MAXN<<2]; 50 51 void Build(int rt,int L,int R) 52 { 53 tree[rt].l = L; tree[rt].r = R; tree[rt].task = -1; 54 if(L == R) 55 return ; 56 int mid = (L+R)>>1; 57 Build(rt<<1,L,mid); 58 Build(rt<<1|1,mid+1,R); 59 } 60 61 void Down(int rt) 62 { 63 if(tree[rt].flag && tree[rt].l != tree[rt].r) 64 { 65 tree[rt<<1].flag = tree[rt<<1|1].flag = tree[rt].flag; 66 tree[rt<<1].task = tree[rt<<1|1].task = tree[rt].task; 67 tree[rt].flag = 0; 68 } 69 } 70 71 void Update(int rt,int L,int R,int task) 72 { 73 if(tree[rt].l == L && tree[rt].r == R) 74 { 75 tree[rt].flag = 1; 76 tree[rt].task = task; 77 return ; 78 } 79 Down(rt); 80 int mid = (tree[rt].l+tree[rt].r)>>1; 81 if(R <= mid) 82 Update(rt<<1,L,R,task); 83 else 84 if(L > mid) 85 Update(rt<<1|1,L,R,task); 86 else 87 { 88 Update(rt<<1,L,mid,task); 89 Update(rt<<1|1,mid+1,R,task); 90 } 91 } 92 93 int Query(int rt,int pos) 94 { 95 Down(rt); // 因为上面可能没有更新到最底部 96 if(tree[rt].l == tree[rt].r) // 找到叶子节点,并返回 97 return tree[rt].task; 98 99 int mid = (tree[rt].l+tree[rt].r)>>1; 100 if(pos <= mid) 101 return Query(rt<<1,pos); 102 else 103 return Query(rt<<1|1,pos); 104 } 105 106 int main() 107 { 108 ios 109 #ifdef ONLINE_JUDGE 110 #else 111 freopen("in.txt","r",stdin); 112 // freopen("out.txt","w",stdout); 113 #endif 114 scanf("%d",&T); 115 rep(cas,1,T) 116 { 117 printf("Case #%d: ",cas); 118 clr(du,0); clr(s,0); clr(e,0); 119 scanf("%d",&N); 120 G.clear(); 121 G.resize(N+5); 122 rep(i,2,N) 123 { 124 scanf("%d %d",&u,&v); 125 G[v].push_back(u); 126 du[u] = 1; 127 } 128 Index = 0; 129 rep(i,1,N) 130 { 131 if(!du[i]) // 找到根节点,然后按照递归的形式找到自己连续的下属 132 { 133 dfs(i); 134 break; 135 } 136 } 137 // 建树 138 Build(1,1,N); 139 scanf("%d",&M); 140 rep(i,1,M) 141 { 142 scanf("%s",op); 143 if(op[0] == 'C') 144 { 145 scanf("%d",&x); 146 printf("%d ",Query(1,s[x])); 147 } 148 else 149 { 150 scanf("%d %d",&x,&y); 151 Update(1,s[x],e[x],y); // 更新的是x这个人的所有下属 152 } 153 } 154 } 155 fclose(stdin); 156 // fclose(stdout); 157 return 0; 158 }