HDU 4366 Successor(线段树 DFS时间戳啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4366

Successor

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 2961    Accepted Submission(s): 689

Problem Description

Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty and ability.Some times Sean will fire one staff.Then one of the fired man’s Subordinates will replace him whose ability is higher than him and has the highest
loyalty for company.Sean want to know who will replace the fired man.

Input

In the first line a number T indicate the number of test cases. Then for each case the first line contain 2 numbers n,m (2<=n,m<=50000),indicate the company has n person include Sean ,m is the times of Sean’s query.Staffs are numbered from 1 to n-1,Sean’s number
is 0.Follow n-1 lines,the i-th(1<=i<=n-1) line contains 3 integers a,b,c(0<=a<=n-1,0<=b,c<=1000000),indicate the i-th staff’s superior Serial number,i-th staff’s loyalty and ability.Every staff ‘s Serial number is bigger than his superior,Each staff has different
loyalty.then follows m lines of queries.Each line only a number indicate the Serial number of whom should be fired.

Output

For every query print a number:the Serial number of whom would replace the losing job man,If there has no one to replace him,print -1.

Sample Input

1
3 2
0 100 99
1 101 100
1
2

Sample Output

2
-1

Author

FZU

Source

2012 Multi-University Training Contest 7

题意:(转)

某公司有 n 个人,编号从 0 到 n-1 ,0号是BOSS。除BOSS外,每个人有忠诚度和能力两个属性,每个人的忠诚度都不同。每个人都有可能被BOSS炒鱿鱼,当某个人被炒后,他的所有下级中能力大于他且具有最大忠诚度的人将取代他的位置。现在给定所有人的上下级关系(下级的编号总是比上级大)和一些被炒鱿鱼的人的编号,输出取代被炒人的人的编号,如果没人取代被炒人,输出“-1”。

PS:首先,把以每个节点为根的子树转化为连续区间以便于处理。然后,按能力值由大到小对员工进行排序,能力值相同时,编号小的排在前面。最后,从左到右求以某个人为根的子树中忠诚度最大的人的编号,然后将根的忠诚度插入到线段树中。

因为每个忠诚值必然对应一个唯一的序号,那么开个 map映射一下好了。

DFS时间戳,记录进入结点的时间戳和出结点的时间戳,两个时间戳之间的都是这个结点的子孙结点了。

代码如下:

#pragma comment(linker,"/STACK:102400000,102400000")  //手动扩栈
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1

const int maxn = 50017;
int n, m;
int Max[maxn << 2], ans[maxn];
int L[maxn], R[maxn], idx;
int vis[maxn];
map<int, int> mm;
vector<int> v[maxn];

struct Staff
{
    int b, c;
    int id;
} s[maxn];

bool cmp(Staff s1, Staff s2)
{
    if(s1.c == s2.c)
    {
        return s1.id < s2.id;
    }
    return s1.c > s2.c;
}

void PushUP(int rt) //把当前结点的信息更新到父结点
{
    Max[rt] = max(Max[rt<<1],Max[rt<<1|1]);
}

void build(int l, int r, int rt)
{
    if(l == r)
    {
        Max[rt] = -1;
        return ;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUP(rt);
}

void update(int p, int c, int l, int r, int rt)
{
    if(l == r)
    {
        Max[rt] = c;
        return ;
    }
    int mid = (l + r) >> 1;
    if(p <= mid)
    {
        update(p , c , lson);
    }
    else
    {
        update(p , c , rson);
    }
    PushUP(rt);
}

int query(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        return Max[rt];
    }
    int mid = (l + r) >> 1;
    int ret = -999;
    if(L <= mid)
    {
        ret = max(ret, query(L , R , lson));
    }
    if(R > mid)
    {
        ret = max(ret, query(L , R , rson));
    }
    return ret;
}

void dfs(int x)
{
    L[x] = idx;
    vis[x] = 1;
    int num = v[x].size();
    for(int i = 0; i < num; i++)
    {
        if(!vis[v[x][i]])
        {
            idx++;
            int tt = v[x][i];
            dfs(tt);
        }
    }
    R[x] = idx;
}

void init()
{
    memset(vis, 0, sizeof(vis));
    for(int i = 0; i < maxn; i++)
    {
        v[i].clear();
    }
    mm.clear();
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d",&n, &m);
        int a, b, c;
        for(int i = 1; i <= n-1; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            v[a].push_back(i);
            s[i].b = b;
            s[i].c = c;
            s[i].id = i;
            mm[b] = i;
        }
        mm[-1] = -1;
        sort(s+1, s+n, cmp);//从大到小
        build(1, n-1, 1);
        idx = 0;

        //DFS时间戳,记录进入结点的时间戳和出结点的时间戳,
        //两个时间戳之间的都是这个结点的子孙结点了
        dfs(0);

        for(int i = 1; i <= n-1; i++)
        {
            int ret = query(L[s[i].id], R[s[i].id], 1, n-1, 1);
            ans[s[i].id] = mm[ret];
            update(L[s[i].id], s[i].b, 1, n-1, 1);
        }
        int k;
        for(int i = 0; i < m; i++)
        {
            scanf("%d",&k);
            printf("%d\n",ans[k]);
        }
    }
    return 0;
}
/*
9
5 3
0 100 99
1 80 100
1 102 150
3 90 50
1
2
3

5 3
0 100 99
1 80 100
2 102 150
3 90 50
1
2
3
*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-28 21:27:58

HDU 4366 Successor(线段树 DFS时间戳啊)的相关文章

hdu 5692 Snacks 线段树+dfs

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1295    Accepted Submission(s): 302 Problem Description 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发

J - Assign the task HDU - 3974 (线段树 + dfs序)

题意:给一颗树,两种操作,查询 i 结点的颜色,和将i结点和它的子树都染成另一种颜色 题解:dfs序构建线段树,对于x和其子树染色就是 l[x] 和 r[x]; dfs序线段树板子 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #include<queue>

HDU 5692 线段树+dfs序

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1779    Accepted Submission(s): 427 Problem Description 百度科技园内有n 个零食机,零食机之间通过n−1 条路相互连通.每个零食机都有一个值v ,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v

线段树+dfs序(Apple Tree )(Assign the task )

线段树+dfs序 给定一棵n个节点的树,m次查询,每次查询需要求出某个节点深度为h的所有子节点. 作为预处理,首先将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致. 然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]. 最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出

Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB 总提交次数:196   AC次数:65   平均分:58.62 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 给定一棵N个节点的树,每个点有一个权值,有M个询问(a,b,c)若a 为1,回答b到c路径上的最小权值,若a为2,回答b到c路径上的最大权值,若a为3,回答b到c路径上的所有权值的

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

Codeforces 384E 线段树+dfs序

题目链接:点击打开链接 题意: 给定n个点,m个询问的无向树(1为根) 下面n个数表示每个点的权值 下面n-1行给出树 操作1:x点权值+v, x的第 i & 1 的儿子-v, 第 !(i&1) 的儿子+v 操作2:询问x点权值 dfs把树转成序列 根据深度把点分成2组 分别用线段树维护.. 然后Y一下 #include<stdio.h> #include<string.h> #include<iostream> #include<algorith

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek