Assign the task HDU - 3974
题面
The company usually assigns some tasks to some employees to finish.When a task is assigned to someone,He/She will assigned it to all his/her subordinates.In other words,the person and all his/her subordinates received a task in the same time. Furthermore,whenever a employee received a task,he/she will stop the current task(if he/she has) and start the new one.
Write a program that will help in figuring out some employee’s current task after the company assign some tasks to some employee.
Input
The first line contains a single positive integer T( T <= 10 ), indicates the number of test cases.
For each test case:
The first line contains an integer N (N ≤ 50,000) , which is the number of the employees.
The following N - 1 lines each contain two integers u and v, which means the employee v is the immediate boss of employee u(1<=u,v<=N).
The next line contains an integer M (M ≤ 50,000).
The following M lines each contain a message which is either
"C x" which means an inquiry for the current task of employee x
or
"T x y"which means the company assign task y to employee x.
(1<=x<=N,0<=y<=10^9)
Output
For each test case, print the test case number (beginning with 1) in the first line and then for every inquiry, output the correspond answer per line.
法一:直接模拟多叉树+线段树
首先,读者可以画个树,自行标号dfs序,体会下dfs序的特点
不难发现,对于任意子树所含的结点编号是连续的
且该子树所含结点最小编号就是根结点编号
然后这个dfs序就是我们解决这道题的关键所在
按题意直接建好多叉树,标好dfs序,然后你会发现其实操作蛮简单的
查询员工,变成一层层去找对应子树根结点
#include <cstdio>
#include <set>
#include <cstring>
using namespace std;
const int maxn = 50005;
struct node{int dat, child, nxt, tag, boss, l, r;}tr[maxn];
int t, n, m, boss, tot, p[maxn], a, b;
void build(int p)
{
tr[p].l = ++tot;
for (int i = tr[p].child; i; i = tr[i].nxt)build(i);
tr[p].r = tot;
}
inline void create(int Boss, int k)
{
tr[k].boss = Boss;
tr[k].nxt = tr[Boss].child;
tr[Boss].child = k;
}
inline void push(int p)
{
if (!tr[p].tag)return;
for (int i = tr[p].child; i; i = tr[i].nxt)
tr[i].dat = tr[i].tag = tr[p].tag;
tr[p].tag = 0;
}
inline void update(int l, int r, int p)
{
if (l == p) { tr[p].dat = tr[p].tag = r; return; }
push(p);
for (int i = tr[p].child; i;i=tr[i].nxt)
if (tr[i].l <= tr[l].l && tr[l].l <= tr[i].r)
update(l, r, i);
}
inline int query(int x, int p)
{
if (x == p) return tr[p].dat?tr[p].dat:-1;
push(p);
for (int i = tr[p].child; i; i = tr[i].nxt)
if (tr[i].l <= tr[x].l && tr[x].l <= tr[i].r)
return query(x, i);
}
int main()
{
scanf("%d", &t);
for (int k = 1; k <= t; ++k)
{
scanf("%d", &n);
printf("Case #%d:\n", k);
memset(tr, 0, sizeof tr);
for (int i = 1; i < n; ++i)
{
int a, b;
scanf("%d%d", &a, &b);
create(b, a);
}
for (int i = 1; i <= n; ++i)if (!tr[i].boss) { boss = i; break; }
build(boss);
scanf("%d", &m);
for (int i = 1; i <= m; ++i)
{
char s[2];
scanf("%s%d", s, &a);
if (s[0] == 'C')printf("%d\n", query(a, boss));
else { scanf("%d", &b); update(a, b, boss); }
}
}
}
法二:并查集+模拟
每次查询,直接往上早,如果boss任务更新时间比当前任务晚,则更新当前任务
#include <cstdio>
using namespace std;
struct node
{int job, time;}a[50005];
int fa[50005], t, n, m, u, v, cnt;
char c[2];
int main()
{
scanf("%d", &t);
for (int cas = 1, cnt = 0; cas <= t; ++cas, cnt = 0)
{
scanf("%d",&n);
for (int i = 1; i <= n; ++i) fa[i] = a[i].job = a[i].time = -1;
for (int i = 1; i < n; ++i) scanf("%d%d",&u,&v), fa[u] = v;
scanf("%d", &m);
printf("Case #%d:", cas);
while (m--)
{
int x;
scanf("%s%d", c, x);
if (c[0] == 'C')
{
int y = a[x].job, tmp = a[x].time;
for (;x != -1;x=fa[x])
if (a[x].time > tmp) y = a[x].job, tmp = a[x].time;
printf("%d\n", &y);
}
else
{
int y; scanf("%d", &y);
a[x].job = y, a[x].time = ++cnt;
}
}
}
return 0;
}

浙公网安备 33010602011771号