题意:每个人都有一个上司,每个人都有能力值和忠诚值,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. caffe的model参数解析numpy多维数组的存取

    在caffe的参数进行Python解析时,需要对模型的wight和bias的参数进行解析,为了提高结果解析的可读性,需要用numpy将解析的文件进行保存 此时用到np.savetxt方法和np.sav ...

  2. would you please...could you please...两句区别是什么?

    Could you please 是can you please 更为礼貌.委婉的说法,并不是过去式,是“能否麻烦你……”.“请你……”的意思,更侧重“能否”及客观情况:回答时要注意,eg:A:“Co ...

  3. (1)打造简单OS-汇编写入引导区,虚拟机启动步骤

    首先需要您在网上下载NASM编译器,可以将汇编编译为二进制文件 1.写一段汇编代码在屏幕上打印一段字符,可以运行的!并进行nasm为二进制文件,如下"test.asm" 该段汇编主 ...

  4. python 将字节写入文本文件

    想在文本模式打开的文件中写入原始的字节数据 将字节数据直接写入文件的缓冲区即可 >>> import sys >>> sys.stdout.write(b'Hell ...

  5. linux常用命令:more 命令

    more命令,功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上. more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会 ...

  6. LCA 最近公共祖先 (模板)

    #include <iostream> #include <stdio.h> #include <cstring> #include <vector> ...

  7. UVA 11100 The Trip, 2007 (贪心)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  8. 018.07 New BMW ICOM A3+B+C+D Plus EVG7 Controller Tablet PC with WIFI Function

    2018.07 New BMW ICOM A3+B+C+D Plus EVG7  Controller Tablet PC with WIFI Function Software Version : ...

  9. 前端框架VUE----vue的使用

    一.安装 对于新手来说,强烈建议大家使用<script>引入 二. 引入vue.js文件 我们能发现,引入vue.js文件之后,Vue被注册为一个全局的变量,它是一个构造函数. 三.使用V ...

  10. Errors occurred during the build. Errors running builder 'Validation' on pro

    选择项目-->右键-->Properties-->Builders   右面有四个选项,把Validation前面勾去掉