题意:每个人都有一个上司,每个人都有能力值和忠诚值,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. python 正则基本方法

    2017-04-11 学习python,免不了应对爬虫,初学爬虫最难理解的就是正则表达式. 比如我们要爬去网页上的某些内容,就像下面这种形式: <p>safdsf</p>< ...

  2. django-pagination 样式修改

    默认 django-pagination  样式: 使用bootstrap后样式: (有些瑕疵,下面来完善一下) 修改后: 效果还不错吧.那么讲下如何修改. 首先找到其源码: (路径:site-pac ...

  3. python pprint

    使用 pprint 模块 pprint 模块( pretty printer ) 用于打印 Python 数据结构. 当你在命令行下打印特定数据结构时你会发现它很有用(输出格式比较整齐, 便于阅读). ...

  4. python 创建临时文件和文件夹

    ----需要在程序执行时创建一个临时文件或目录,并希望使用完之后可以自动销毁掉. tempfile 模块中有很多的函数可以完成这任务.为了创建一个匿名的临时文件,可以使用tempfile.Tempor ...

  5. 20165305 苏振龙《Java程序设计》第五周学习总结

    第七章 Java支持在一个类中声明另一个类,这样的类称作内部类,而包含内部类的类成为内部类的外嵌类. 和某类有关的匿名类就是该类的一个子类,该子类没有明显的用类声明来定义,所以称做匿名类. 和某接口有 ...

  6. 什么是FEBS

    FEBS后台权限管理系统      FEBS是一个简单高效的后台权限管理系统.项目基础框架采用全新的Java Web开发框架 —— Spring Boot2.0.4,消除了繁杂的XML配置,使得二次开 ...

  7. arcgis desktop 地理编码服务发布

    1.创建地址定位器 2.创建复合地址定位器 3.鼠标右键,共享为,地理编码服务.

  8. 前端框架VUE----面向对象

    JavaScript 语言中,生成实例对象的传统方法是通过构造函数. function Animal(name,age){ this.name = name; this.age = age; } An ...

  9. 使用My97DatePicker设置日期的属性示例

    <td>交易日期:</td> <td colspan="3"> <input class="Wdate" id=&qu ...

  10. 在配置好环境以后,启动tomcat后,出现这个异常

    15-Apr-2019 16:48:13.299 严重 [RMI TCP Connection(3)-127.0.0.1] org.apache.catalina.core.StandardConte ...