Successor HDU - 4366 (预处理,线段树,dfs序)
Successor
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.
第一行一个整数,表示测试数据组数。
对于每组数据,第一行两个整数n和m,表示公司的员工和询问次数。
接下来n-1行,第i行,3个整数,i的上级,忠诚度,能力值。老总的编号为0,所有员工的忠诚度都不一样。
接下来m行,每行一个整数,表示要开除某个人,你需要输出替代他的员工编号。如果不存在,输出-1.
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.
对于每个要开除的人,你需要输出替代他的员工编号。如果不存在,输出-1.
Sample Input
1
3 2
0 100 99
1 101 100
1
2
Sample Output
2
-1
题意:
公司里自上而下是一个树形结构。
每个员工都有一个忠诚度和能力值。如果把一个员工开除,需要在他的下属中,找到一个能力值比他高,且忠诚度最大的员工来替代他。
m个询问,每行一个整数,表示要开除某个人,你需要输出替代他的员工编号。如果不存在,输出-1.
思路:
一棵树的子树中,dfs序是连续的。
所以我们先通过dfs来把树形问题转为区间问题。
又因为所有员工的忠诚度都不一样。 所以我们可以用一个map把员工的编号和忠诚度对应起来。
我们先以员工的能力值为指标,降序排序。
然后预处理出所有答案,输入直接O(1) 输出结果。
如何预处理出所有员工节点的答案呢?
我们知道推论①:一个员工对他的领导的答案值有影响,当且仅当这个员工的能力值大于他的那个领导的答案值。
那么我们可以在排序后,
在线段树中从大到小依次加入员工,
这样的话我们对一个员工,询问线段树中这个员工的dfs序的时间戳区间中的忠诚度的最大值。(区间查询)
中横渡对应下编号就是这个员工的答案。
然后把这位员工的忠诚度加入到员工的dfs序的时间戳位置中。(单点更新)
为什么这样对?
因为对上面讲到的推论①,对其可能有影响的员工已经全部加入到线段树中了。
他只需要询问在自己的下属员工中(在时间戳区间中)的忠诚度最大值即可。
细节见代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
// #define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 50010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int T;
map<int, int> mp;
std::vector<int> son[maxn];
int tree[maxn << 2];
int ans[maxn];
int n, m;
int tot;
void init()
{
repd(i, 1, n * 4) {
tree[i] = -1;
}
tot = 0;
mp.clear();
repd(i, 0, n) {
son[i].clear();
ans[i] = -1;
}
mp[-1] = -1;
}
struct node {
int ab;
int lo;
int id;
int timel;
int timer;
bool operator <(const node &bb )const
{
if (ab != bb.ab) {
return ab > bb.ab;
} else {
return timel < bb.timel;
}
}
} data[maxn];
void dfs(int x)
{
data[x].timel = ++tot;
for (auto y : son[x]) {
dfs(y);
}
data[x].timer = tot;
}
int ask(int rt, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr) {
return tree[rt];
}
int res = -1;
int mid = (l + r) >> 1;
if (ql <= mid) {
res = max(res, ask(rt << 1, l, mid, ql, qr));
}
if (qr > mid) {
res = max(res, ask(rt << 1 | 1, mid + 1, r, ql, qr));
}
return res;
}
void update(int rt, int l, int r, int pos, int val)
{
if (l == r && l == pos) {
tree[rt] = val;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) {
update(rt << 1, l, mid, pos, val);
}
if (pos > mid) {
update(rt << 1 | 1, mid + 1, r, pos, val);
}
tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]);
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &m);
init();
int x;
repd(i, 1, n - 1) {
scanf("%d %d %d", &x, &data[i].lo, &data[i].ab);
data[i].id = i;
mp[data[i].lo] = i;
son[x].push_back(i);
}
dfs(0);
sort(data + 1, data + n);
for (int i = 1; i < n; ++i) {
ans[data[i].id] = mp[ask(1, 1, tot, data[i].timel, data[i].timer)];
update(1, 1, tot, data[i].timel, data[i].lo);
}
while (m--) {
int x;
scanf("%d", &x);
printf("%d\n", ans[x] );
}
}
return 0;
}
inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
} else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}
Successor HDU - 4366 (预处理,线段树,dfs序)的更多相关文章
- S - Query on a tree HDU - 3804 线段树+dfs序
S - Query on a tree HDU - 3804 离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- BZOJ_3252_攻略_线段树+dfs序
BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...
- 【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
题目大意 Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- HDU 5692 线段树+dfs序
Snacks Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数
R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...
- hdu 5039 线段树+dfs序
http://acm.hdu.edu.cn/showproblem.php?pid=5039 给定一棵树,边权为0/1.m个操作支持翻转一条边的权值或者询问树上有多少条路径的边权和为奇数. 用树形df ...
- 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序
3779: 重组病毒 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 224 Solved: 95[Submit][Status][Discuss] ...
- 【BZOJ-3306】树 线段树 + DFS序
3306: 树 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 792 Solved: 262[Submit][Status][Discuss] De ...
随机推荐
- unmix和conditional average:消混叠和条件均值
unmix 该程序用来消除“像素混叠”.所谓像素混叠,是值在自然场景的图像中,边缘线成像到cmos的像素上时,某些像素会刚好跨在该边缘线上. 这样的像素特点就是,其R.G.B三色像素梯度值不一致.比如 ...
- Spring IoC的形象化理解
1.IoC(控制反转) 首先想说说IoC(Inversion of Control,控制反转).这是spring的核心,贯穿始终.所谓IoC,对于spring框架来说,就是由spring来负责控制对象 ...
- C++学习笔记-继承中的构造与析构
C++存在构造函数与析构函数,继承中也存在构造和析构函数.继承中的构造和析构函数与普通的构造析构有细微差别. 赋值兼容性原则 #include "iostream" using n ...
- Go语言中方法和函数的区别
今天看<Go语言实战>发现方法和函数不太一样,写的格式不一样,用法也不一样.所以记一次笔记. 在Go语言中,函数和方法不太一样,有明确的概念区分.其他语言中,比如Java,一般来说,函数就 ...
- C语言Ⅰ博客作业07
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-3/homework/9933 我在这个课程的目 ...
- 2019牛客暑期多校训练营(第七场)-H Pair(数位dp)
题目链接:https://ac.nowcoder.com/acm/contest/887/H 题意:给定A,B,C,求有多少对(x,y)满足x&y>C或者x^y<C,其中1< ...
- Oracle-DQL 4- 多表查询
多表查询: 1.笛卡尔积SELECT * FROM dept;--查询员工的信息和其所在部门的信息SELECT ename,job,dname,locFROM emp,dept; --集合A中的所有元 ...
- PAT B1042 挖掘机哪家强
AC代码 #include <cstdio> #include <algorithm> using namespace std; const int max_n = 11000 ...
- Lua 截取字符串(截取utf-8格式字符串)
对utf-8完全没概念的可以看看我上一篇随笔:简单说说utf-8编码格式 另外,还要知道string.sub 和 string.byte 的用法. 先上完整代码: local StringHelper ...
- Unity Button按钮延迟
1.把下面脚本放到Editor文件夹下,这样脚本继承Button之后,新声明的public变量才能在Inspector面板显示出来. using System.Collections; using S ...