题意:每个人都有一个上司,每个人都有能力值和忠诚值,0是老板,现在给出m个询问,每次询问给出一个x,要求你找到x的所有直系和非直系下属中能力比他高的最忠诚的人是谁

思路:因为树上查询很麻烦,所以我们直接dfs序把关系变成线性。然后我们再分块,把每个块按照能力值升序排列,这样我们就能直接二分查找这个块内能力值大于x的数就是二分出来的数到块末尾的所有数。但是怎么查找最忠诚的?我们直接预处理每个块内i位置到块末尾的最忠诚人的位置就行了。

代码:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = + ;
const int MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
struct node{
int name, loyalty, ability;
bool operator < (const node &x) const{
return ability < x.ability;
}
}p[maxn];
int loyalty[maxn], ability[maxn];
int in[maxn], out[maxn]; //在dfs序列中的位置1-id
int belong[maxn], id;
int head[maxn], tot;
struct Edge{
int to, next;
}edge[maxn];
void init(){
tot = id = ;
memset(head, -, sizeof(head));
}
void addEdge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void dfs(int u){
in[u] = ++id;
p[id].ability = ability[u], p[id].loyalty = loyalty[u], p[id].name = u;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
dfs(v);
}
out[u] = id;
}
int MaxLoy[maxn]; //从位置j到所属块末尾的最大loyalty的人在dfs序列的位置
int n, m, block, sz;
int solve(int x){
int l = belong[in[x]], r = belong[out[x]];
int L, R;
int MaxLoyalty = -, ans = -; L = block * (l - ) + , R = min(L + block - , id);
for(int i = L; i <= R; i++){
if(in[p[i].name] > in[x] && out[p[i].name] <= out[x]){
if(p[i].loyalty > MaxLoyalty && p[i].ability > ability[x]){
MaxLoyalty = p[i].loyalty;
ans = p[i].name;
}
}
}
L = l + , R = r - ;
node c;
c.ability = ability[x];
for(int i = L; i <= R; i++){
int s = block * (i - ) + , e = s + block;
int pos = upper_bound(p + s, p + e, c) - p;
if(pos >= e) continue;
int tmp = MaxLoy[pos];
if(p[tmp].loyalty > MaxLoyalty){
MaxLoyalty = p[tmp].loyalty;
ans = p[tmp].name;
}
}
L = block * (r - ) + , R = min(L + block - , id);
for(int i = L; i <= R; i++){
if(in[p[i].name] > in[x] && out[p[i].name] <= out[x]){
if(p[i].loyalty > MaxLoyalty && p[i].ability > ability[x]){
MaxLoyalty = p[i].loyalty;
ans = p[i].name;
}
}
}
return ans;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
init();
int a;
scanf("%d%d", &n, &m);
ability[] = -, loyalty[] = -;
for(int i = ; i <= n - ; i++){
scanf("%d%d%d", &a, &loyalty[i], &ability[i]);
addEdge(a, i);
}
dfs();
block = (int)sqrt(id * 1.0);
for(int i = ; i <= id; i++){
belong[i] = (i - ) / block + ;
}
sz = belong[id];
for(int i = ; i <= sz; i++){
int s = block * (i - ) + , e = min(s + block, id + );
sort(p + s, p + e);
int Max = -, pos;
for(int j = e - ; j >= s; j--){
if(Max < p[j].loyalty){
Max = p[j].loyalty;
pos = j;
}
MaxLoy[j] = pos;
}
}
while(m--){
scanf("%d", &a);
printf("%d\n", solve(a));
}
}
return ;
}

HDU 4366 Successor(dfs序 + 分块)题解的更多相关文章

  1. HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护

    给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示d ...

  2. HDU 4366 Successor( DFS序+ 线段树 )

    Successor Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  3. HDU - 4366 Successor DFS区间+线段树

    Successor:http://acm.hdu.edu.cn/showproblem.php?pid=4366 参考:https://blog.csdn.net/colin_27/article/d ...

  4. HDU.5692 Snacks ( DFS序 线段树维护最大值 )

    HDU.5692 Snacks ( DFS序 线段树维护最大值 ) 题意分析 给出一颗树,节点标号为0-n,每个节点有一定权值,并且规定0号为根节点.有两种操作:操作一为询问,给出一个节点x,求从0号 ...

  5. hdu 4366 Successor - CDQ分治 - 线段树 - 树分块

    Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty an ...

  6. HDU 4366 Successor 分块做法

    http://acm.hdu.edu.cn/showproblem.php?pid=4366 今日重新做了这题的分块,果然是隔太久了,都忘记了.. 首先,用DFS序变成一维的问题 关键是它有两个权值, ...

  7. HDU4366 Successor【dfs序 分块】

    HDU4366 Successor 题意: 给出一棵根为\(1\)的树,每个点有两个权值\(x,y\),每次询问一个点的子树中\(x\)比这个点的\(x\)大且\(y\)值最大的那个点 题解: 如果以 ...

  8. 【HDU4366】【DFS序+分块】Successor

    Problem Description Sean owns a company and he is the BOSS.The other Staff has one Superior.every st ...

  9. HDU 3974 Assign the task(DFS序)题解

    题意:给出一棵树,改变树的一个节点的值,那么该节点及所有子节点都变为这个值.给出m个询问. 思路:DFS序,将树改为线性结构,用线段树维护.start[ ]记录每个节点的编号,End[ ]为该节点的最 ...

随机推荐

  1. CNN超参数优化和可视化技巧详解

    https://zhuanlan.zhihu.com/p/27905191 在深度学习中,有许多不同的深度网络结构,包括卷积神经网络(CNN或convnet).长短期记忆网络(LSTM)和生成对抗网络 ...

  2. Sitecore营销自动化

    增加与战略性自动化营销系统的互动 Sitecore营销自动化基于DMS中的Sitecore个性化功能.营销自动化系统使用诸如位置,设备和先前访问或购买之类的客户数据来影响用户沿着购买路径的旅程.这些系 ...

  3. Java基础语法(一 )

    一.关键字 关键字概述 被Java语言赋予特定含义的单词 关键字特点 组成关键字的字母全部小写 关键字注意事项 goto和const作为保留字存在,目前并不使用 关键字单词 用于定义数据类型的关键字 ...

  4. python windows安装 SQLServer pymssql,

    1.到正儿八经的网站下载文件,找到适合自己的版本 2.把文件放到一个地方,能让pip找到就行, 不放scripts下面的话, 恐怕会报错“FileNotFoundError" 3. 走到pi ...

  5. 20165215 实验三 敏捷开发与XP实践

    20165215 实验三 敏捷开发与XP实践 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:张家佳 学号:20165215 指导教师:娄嘉鹏 实验日期:2018年4月28日 实验时 ...

  6. linux screen 多任务后台执行

    1.安装工具:yum install -y screen 2.进入新screen界面:screen 3.回到原命令行:先按CTRL+a,然后再按d 4.查看现有的screen回话:screen -ls ...

  7. linux 下 tomcat 运行报错 Broken pipe

    linux 下 tomcat 运行报错 Broken pipe 感谢:http://hi.baidu.com/liupenglover/blog/item/4048c23ff19f1cd67d1e71 ...

  8. vue中组件通信之子父通信

    <div id="app"> <parent-comp1></parent-comp1> <parent-comp1></pa ...

  9. tcpdump 命令

    tcpdump命令高级网络 tcpdump命令是一款sniffer工具,它可以打印所有经过网络接口的数据包的头信息,也可以使用-w选项将数据包保存到文件中,方便以后分析. 选项 -a:尝试将网络和广播 ...

  10. xml.dom——文档对象模型API

    文档对象模型,或者“DOM”,是一个跨语言API的World Wide Web Consortium(W3C)来访问和修改XML文档.DOM的实现提供了一个XML文档树结构,或允许客户机代码从头开始建 ...