链接:http://acm.hdu.edu.cn/showproblem.php?pid=3974
题意:给出一个公司的组成,当有新任务给某个人的时候, 他的下属也会帮他做, 当有新的任务下达时, 他们会停下原来的工作来做新的工作。
输入:T组数据, 每组先输入n, 接下来n-1行 每行输入 u, v 代表v是u的上司, 下一行输入m,接下来m行代表操作, 其中 T x y代表给x新下达了y的任务 , C x 代表查询x正在做什么工作。
解题思路:
线段树做法:
首先将关系映射成线段的形式, 映射的方式是通过两个数组, 一个储存节点新获得编号(比如根节点为1),另一个数组表示紧跟其编号后多少个编号是他的下属, 这样映射完就会发现每一个人及他的下属都构成了线段, 且老总是[1, n], 随着等级降低线段越来越短, 然后套一下线段树就可以了。暴力做法:
开一个结构体数组,三个变量:他上司的编号, 下达最后对他下达任务的时间,最后下达的任务
将每一个下属的对应数组位置储存他上司的编号。
询问时对他及他的上司遍历,取最晚下达的任务。
线段树代码
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <string.h>
#include <queue>
#define LL long long
#define mid (l+r)/2
#define lson ins<<1
#define rson ins<<1|1
using namespace std;
const int Max = 50005;
const int MOD = 1e9 + 7;
int head[Max], nxt[Max];//head表示映射完以后对应的编号, nxt有多少连续节点是他的子节点
vector<int> edge[Max];
struct node {
int l, r, sum;
} tree[Max << 2];
void build(int l, int r, int ins) {
tree[ins].l = l, tree[ins].r = r, tree[ins].sum = -1;
if (l == r)return;
else {
build(l, mid, lson);
build(mid + 1, r, rson);
}
}
void updata(int ql, int qr, int ins, int add) {
int l = tree[ins].l, r = tree[ins].r;
if (l >= ql && r <= qr) {
tree[ins].sum = add;
} else {
if (tree[ins].sum != -1) {//如果当前已经被标记, 则将当前的下推
updata(l, mid, lson, tree[ins].sum);
updata(mid + 1, r, rson, tree[ins].sum);
tree[ins].sum = -1;
}
if (ql <= mid)updata(ql, qr, lson, add);
if (qr > mid)updata(ql, qr, rson, add);
}
}
int query(int en, int ins) {
int l = tree[ins].l, r = tree[ins].r;
if (l == r || tree[ins].sum != -1) {//因为第一个查到的永远是最后下达的任务
return tree[ins].sum;
} else {
if (en <= mid)return query(en, lson);
else return query(en, rson);
}
}
void Dfs(int ins, int &pos) {//编号 注意pos是取地址的
head[ins] = pos;
for (int a = 0; a < (int) edge[ins].size(); a++) {
Dfs(edge[ins][a], ++pos);
nxt[ins] += nxt[edge[ins][a]];
}
nxt[ins] += (int) edge[ins].size();
}
int main() {
int T, cases = 1;
scanf("%d", &T);
while (T--) {
int n, u, v;
scanf("%d", &n);
build(1, n, 1);
memset(nxt, 0, sizeof(nxt));
memset(head, 0, sizeof(head));
for (int a = 1; a <= n; a++)edge[a].clear();
for (int a = 0; a < n - 1; a++) {
scanf("%d%d", &u, &v);
edge[v].push_back(u);
head[u] = 1;时
}
int pos = 1;
for (int a = 1; a <= n; a++) {
if (!head[a]) {
Dfs(a, pos);
break;
}
}
int m;
char opera[3];
scanf("%d", &m);
printf("Case #%d:\n", cases++);
for (int a = 0; a < m; a++) {
scanf("%s", opera);
if (opera[0] == 'T') {
int i, j;
scanf("%d%d", &i, &j);
updata(head[i], head[i] + nxt[i], 1, j);
} else {
int i;
scanf("%d", &i);
printf("%d\n", query(head[i], 1));
}
}
}
return 0;
}
暴力代码
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <string.h>
#include <queue>
#define LL long long
#define mid (l+r)/2
#define lson ins<<1
#define rson ins<<1|1
using namespace std;
const int Max = 50005;
const int MOD = 1e9 + 7;
int ans;
struct node {
int times, names, h;
} f[Max];
void getf(int i, int max1) {
if (f[i].times > max1) {
max1 = f[i].times;
ans = f[i].h;
}
if (f[i].names == i) {
return;
}
getf(f[i].names, max1);
}
int main() {
int T, cases = 1;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
for (int a = 1; a <= n; a++) {
f[a].names = a;
f[a].times = 0;
}
for (int a = 0; a < n - 1; a++) {
int u, v;
scanf("%d%d", &u, &v);
f[u].names = v;
}
int m, ts = 1;
char opera[3];
scanf("%d", &m);
printf("Case #%d:\n", cases++);
for (int a = 0; a < m; a++) {
scanf("%s", opera);
if (opera[0] == 'T') {
int i, j;
scanf("%d%d", &i, &j);
f[i].times = ts++;
f[i].h = j;
} else {
int i;
ans = -1;
scanf("%d", &i);
getf(i, 0);
printf("%d\n", ans);
}
}
}
return 0;
}