[hihoCoder#1065]全图传送

试题描述

先知法里奥是 Dota 系列中的一个英雄。机动性强,推塔能力一流,打钱速度快,传送技能使先知可以全地图支援。在后期比拼中通过强大的兵线控制能力使得对方的兵线一直难以过河,并具有一定的后期 DPS 能力。

我们今天要考虑的是传送技能。假设战场是一个树形区域,每个节点有一个权值 vi。当你传送到某个点 u 时,可以支援距离点 u 半径 r 以内的所有节点。请对于下列询问"u r", 回答以 u 节点为中心,半径 r 以内的节点中,权值最大的节点的编号是多少。如果有多个节点,返回编号最小的。

输入

第一行包含一个整数 n (1 ≤ n ≤ 105),表示节点总数。

接下来的一行,包含 n 个数字,表示每个节点的权值 vi (1 ≤ vi ≤ 109)。 接下来的 n-1 行,每行三个整数 (aibi,wi),表示一条连接 aibi 节点的边,边长为 wi(1 ≤ ai, bi ≤ n, 1 ≤ wi ≤ 104)。

接下来的一行包含一个整数 q,表示询问总数(1 ≤ q ≤ 105)。 接下来 q 行,每行包含两个整数 ur(1 ≤ u ≤ n, 0 ≤ r ≤ 109),表示询问以 u 节点为中心,半径 r 以内的节点中,权值最大的节点的编号是多少。如果有多解返回编号最小的。

输出

对于每组询问,输出一行表示对应答案。

输入示例


输出示例


数据规模及约定

见“输入

题解

考虑离线处理每个操作,把操作所对应的节点记录到节点信息上,考虑使用点分治。显然可以递归每次减小问题规模,考虑跨中点的部分,我们 dfs 并记录每个节点的深度和权值,按照深度为关键词排序,处理一下前缀最大值,对于一个询问,我们二分一下更新答案即可。

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 100010
#define maxm 200010
#define oo 2147483647
int n, m, head[maxn], nxt[maxm], to[maxm], dist[maxm], val[maxn], ans[maxn]; void AddEdge(int a, int b, int c) {
to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
return ;
} int q, m2, h2[maxn], n2[maxn];
struct Que {
int u, r;
Que() {}
Que(int _, int __): u(_), r(__) {}
bool operator < (const Que& t) const { return r < t.r; }
} qs[maxn]; bool vis[maxn];
int root, f[maxn], siz[maxn], size;
void getroot(int u, int fa) {
siz[u] = 1; f[u] = 0;
for(int e = head[u]; e; e = nxt[e]) if(to[e] != fa && !vis[to[e]]) {
getroot(to[e], u);
siz[u] += siz[to[e]];
f[u] = max(f[u], siz[to[e]]);
}
f[u] = max(f[u], size - siz[u]);
if(f[u] < f[root]) root = u;
return ;
}
int ToT, ns[maxn];
Que A[maxn];
void dfs(int u, int d, int fa) {
A[++ToT] = Que(u, d);
for(int e = head[u]; e; e = nxt[e]) if(to[e] != fa && !vis[to[e]])
dfs(to[e], d + dist[e], u);
return ;
}
void solve(int u) {
// printf("u: %d\n", u);
vis[u] = 1;
A[ToT = 1] = Que(u, 0);
for(int e = head[u]; e; e = nxt[e]) if(!vis[to[e]])
dfs(to[e], dist[e], u);
sort(A + 1, A + ToT + 1);
// for(int i = 1; i <= ToT; i++) printf("%d %d\n", A[i].u, A[i].r);
for(int i = 1; i <= ToT; i++) ns[i] = A[i].u;
for(int i = 2; i <= ToT; i++)
if(val[A[i-1].u] > val[A[i].u]) A[i].u = A[i-1].u;
else if(val[A[i-1].u] == val[A[i].u] && A[i-1].u < A[i].u) A[i].u = A[i-1].u;
for(int i = 1; i <= ToT; i++)
for(int u = h2[ns[i]]; u; u = n2[u]) {
// printf("%d q[u]: %d\n", ns[i], u);
Que& que = qs[u];
if(que.r < A[i].r) continue;
int x = upper_bound(A + 1, A + ToT + 1, Que(0, que.r - A[i].r)) - A;
if(x <= ToT && A[x].r <= que.r - A[i].r) x++;
x--;
if(ans[u] == oo) ans[u] = A[x].u;
else if(val[ans[u]] < val[A[x].u]) ans[u] = A[x].u;
else if(val[ans[u]] == val[A[x].u] && ans[u] > A[x].u) ans[u] = A[x].u;
}
for(int e = head[u]; e; e = nxt[e]) if(!vis[to[e]]) {
root = 0; f[0] = n + 1; size = siz[to[e]]; getroot(to[e], u);
solve(root);
}
return ;
} int main() {
n = read();
for(int i = 1; i <= n; i++) val[i] = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read(), c = read();
AddEdge(a, b, c);
}
q = read();
for(int i = 1; i <= q; i++) {
int u = read(), r = read();
qs[i] = Que(u, r);
n2[++m2] = h2[u]; h2[u] = m2;
} for(int i = 1; i <= q; i++) ans[i] = oo;
root = 0; f[0] = n + 1; size = n; getroot(1, 0);
solve(root); for(int i = 1; i <= q; i++) printf("%d\n", ans[i]); return 0;
}

[hihoCoder#1065]全图传送的更多相关文章

  1. 【hiho1065】全图传送

    题目大意:给定一棵 N 个节点的树,点有点权,边有边权,给定 M 个询问,每次询问距离 U 节点不超过 R 的点集中,点权最大的点的编号是多少,若有相同点权,取编号较小的点. 题解: 发现是多组询问, ...

  2. hihoCoder Challenge 3

    #1065 : 全图传送 时间限制:30000ms 单点时限:3000ms 内存限制:256MB 描述 先知法里奥是 Dota 系列中的一个英雄.机动性强,推塔能力一流,打钱速度快,传送技能使先知可以 ...

  3. ACM学习历程—Hihocoder 1291 Building in Sandbox(dfs && 离线 && 并查集)

    http://hihocoder.com/problemset/problem/1291 前几天比较忙,这次来补一下微软笔试的最后一题,这题是这次微软笔试的第四题,过的人比较少,我当时在调试B题,没时 ...

  4. hihocoder -1121-二分图的判定

    hihocoder -1121-二分图的判定 1121 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大家好,我是小Hi和小Ho的小伙伴Net ...

  5. Hihocoder 太阁最新面经算法竞赛18

    Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus ...

  6. hihoCoder太阁最新面经算法竞赛15

    hihoCoder太阁最新面经算法竞赛15 Link: http://hihocoder.com/contest/hihointerview24 题目1 : Boarding Passes 时间限制: ...

  7. 【hihoCoder 1454】【hiho挑战赛25】【坑】Rikka with Tree II

    http://hihocoder.com/problemset/problem/1454 调了好长时间,谜之WA... 等我以后学好dp再来看为什么吧,先弃坑(╯‵□′)╯︵┻━┻ #include& ...

  8. 【hihocoder#1413】Rikka with String 后缀自动机 + 差分

    搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...

  9. 图片采用base64压缩,可以以字符串的形式传送base64给服务端转存为图片

    (function () { var coverImage = document.querySelector('<div id="coverImage">file< ...

随机推荐

  1. mysql 字符串

    mysql中一个字符串,既可以用两个单引号表示,也可以用两个双引号表示. 比如字符串 wangxiaowei,用单引号表示 'wangxiaowei',双引号表示"wangxiaowei&q ...

  2. 中缀表达式转后缀表达式(用于求字符串表达式值)(js栈和队列的实现是通过数组的push和unshift方法插值,pop方法取值)

    中缀表达式:就是我通常用的算术或逻辑公式: 后缀表达式:不包含括号,运算符放在两个运算对象后面,所有的计算按运算符出现的顺序,严格从左向右进行,不用考虑运算符优先级: 如,(2+1)*3 转换后,2 ...

  3. JS实现元素拖动

    实现1 参考文献:http://www.cnblogs.com/cloudgamer/archive/2008/11/17/Drag.html 1.1 拖放效果 <!DOCTYPE html P ...

  4. JS转码

    JS转码是解决XSS漏洞的方案,XSS漏洞是指对dom操作时,出现特殊字符造成的安全泄露. XSS漏洞的主要来源有: 1.URL(需要对url进行encodeURIComponent转码). 2.数据 ...

  5. yourphp读取不到hits

    源代码 <YP:list name="Article" order="id desc" catid="37" limit=" ...

  6. 整理一下Entity Framework的查询

    整理一下Entity Framework的查询 2012-08-30 13:41:59 标签:Entity Framework 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信 ...

  7. springmvc请求参数获取的几种方法

    1.直接把表单的参数写在Controller相应的方法的形参中,适用于get方式提交,不适用于post方式提交. /** * 1.直接把表单的参数写在Controller相应的方法的形参中 * @pa ...

  8. 浅谈T-SQL中的特殊联结

    引言 上一篇博客我们介绍了交叉联接,内联接,外联接3种基本的联接操作.这一篇文章我们介绍一些特殊的联接操作. 组合联接 组合联接就是联接条件涉及到联接两边的多个列的查询.当需要根据主键-外键关系来联接 ...

  9. NERD_commenter——VIM批量注释与反注释插件

    转自:http://www.xefan.com/archives/83568.html 这是对程序员非常实用的一款插件,支持多种语言的补全,还支持单行注释,批量注释,等各种命令映射. 使用方法,先下载 ...

  10. 如何向git账号上提交代码

    官方说明:https://help.github.com/articles/generating-ssh-keys/ 1,为Github账户设置SSH key 文章地址:http://zuyunfei ...