HDU 3974 Assign the task——线段树

来源:互联网 发布:中国特色社会主义 知乎 编辑:程序博客网 时间:2024/06/05 16:28

题意:有一个公司,有n个人,这些人之间的关系是一棵树,公司会安排一些任务给他们, 每次安排至安排一个人,但是他的下属会和他一起做,要求查询当前这个人在做什么工作

思路:一开始不好往线段树那里想,想用线段树的lazy思想直接处理原来的树,但发现更新和查询都没法精确定位,最坏的情况为O(n),会超时,所以考虑如何在更短的时间内更新和查询,这就想到了线段树,可以在O(nlogn)内完成更新和查询

想用线段树解决问题的话首先要把原来的树重建,把做同样工作的人放在一起,这个用一个dfs和一个数组date【】就可以实现,每次dfs到一个点u就date【++cnt】 = u,这样就能保证相同工作的人在一起了。

在dfs的过程中,我们还需要及时得到一个点的所有子节点数,即一个boss的所有员工数,方便更新时根据boss的位置获得更新区间

然后把原来树的节点和date【】做一个映射,一遍根据原来节点的编号的到他在date【】中的位置

线段树维护的是每个叶子的情况,不需要维护区间加法,所以只用一个lazy数组就可以解决问题,具体参考代码

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;const int maxn = 5 *1e5 + 10;char c;int T, n, m, a, b, cnt, rudu[maxn], date[maxn], shuliang[maxn], yingshe[maxn];int lazy[maxn<<2];vector<int> tree[maxn];void init() {    cnt = 0;    memset(rudu, 0, sizeof(rudu));    memset(lazy, -1, sizeof(lazy));    for (int i = 1; i <= n; i++) {        tree[i].clear();    }}int dfs(int u) {    date[++cnt] = u;    if (tree[u].empty()) return shuliang[u] = 0;    int temp = 0;    for (int i = 0; i < tree[u].size(); i++) {        int v = tree[u][i];        temp += dfs(v) + 1;    }    return shuliang[u] = temp;}void pushdown(int root) {    if (lazy[root] != -1) {        lazy[root<<1] = lazy[root<<1|1] = lazy[root];        lazy[root] = -1;    }}void update_interval(int L, int R, int root, int uL, int uR, int val) {    if (uL <= L && R <= uR) {        lazy[root] = val;        return;    }    int mid = (L + R)>>1;    pushdown(root);    if (uL <= mid) {        update_interval(L, mid, root<<1, uL, uR, val);    }    if (uR > mid) {        update_interval(mid + 1, R, root<<1|1, uL, uR, val);    }}int query(int L, int R, int root, int pos) {    if (L == R) {        return lazy[root];    }    int mid = (L + R)>>1;    pushdown(root);    if (pos <= mid) {        return query(L, mid, root<<1, pos);    }    else {        return query(mid + 1, R, root<<1|1, pos);    }}int main(){    scanf("%d", &T);    for (int kase = 1; kase <= T; kase++) {        scanf("%d", &n);        init();        for (int i = 1; i <= n - 1; i++) {            scanf("%d %d", &a, &b);            tree[b].push_back(a);            rudu[a]++;        }        for (int i = 1; i <= n; i++) {            if (!rudu[i]) {                dfs(i);                break;            }        }        for (int i = 1; i <= n; i++) {            yingshe[date[i]] = i;        }        scanf("%d", &m);        printf("Case #%d:\n", kase);        while (m--) {            cin >> c;            if (c == 'T') {                scanf("%d %d", &a, &b);                update_interval(1, n, 1, yingshe[a], yingshe[a] + shuliang[a], b);            }            else {                scanf("%d", &a);                printf("%d\n", query(1, n, 1, yingshe[a]));            }        }    }    return 0;}


原创粉丝点击