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

题解:

发现是多组询问,而且涉及的问题很难通过子树信息合并来解决。同时距离 U 节点不超过 R 等价于 U 与 V 路径距离不超过 R,可以考虑点分治求解。

先将询问离线。点分治的过程中维护一个 map<> 表示距离当前分治的根节点距离恰好为 R 的最优点的编号,可以通过在分治过程中遍历一遍子树求得,时间复杂度为 \(O(nlogn)\),再利用维护得 map 进行构造出距离当前分治中心距离不超过 R 的最优解,即:利用 map 的前一项更新后一项即可。处理出这个之后,再进行遍历子树的操作,对于遍历到的每个点进行查询并更新答案即可。总时间复杂度为 \(O(nlog^2n)\)。

代码如下

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int maxn=1e5+10;
typedef long long LL;
typedef pair<int,int> P; int n,m,val[maxn],ans[maxn];
vector<P> q[maxn]; // [r, id]
struct node{int nxt,to;LL w;}e[maxn<<1];
int tot=1,head[maxn];
inline void add_edge(int from,int to,LL w){
e[++tot]=node{head[from],to,w},head[from]=tot;
}
int rt,sn,sz[maxn],f[maxn];
LL d[maxn];
map<LL,int> rec;
bool vis[maxn];
void getrt(int u,int fa){
sz[u]=1,f[u]=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa||vis[v])continue;
getrt(v,u);
f[u]=max(f[u],sz[v]);
sz[u]+=sz[v];
}
f[u]=max(f[u],sn-sz[u]);
if(!rt||f[u]<f[rt])rt=u;
} int better(int x,int y){
return val[x]>val[y]||(val[x]==val[y]&&x<y)?x:y;
}
void getdis(int u,int fa,LL dist){
auto it=rec.find(dist);
if(it==rec.end())rec[dist]=u;
else rec[dist]=better(rec[dist],u);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to; LL w=e[i].w;
if(v==fa||vis[v])continue;
getdis(v,u,dist+w);
}
}
void update(int u,int fa,LL dist){
for(auto p:q[u]){
LL r=p.fi; int id=p.se;
auto it=rec.upper_bound(r-dist);
if(it!=rec.begin()){
--it;
if(!ans[id])ans[id]=it->se;
else ans[id]=better(ans[id],it->se);
}
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to; LL w=e[i].w;
if(v==fa||vis[v])continue;
update(v,u,dist+w);
}
}
void dfs(int u){
vis[u]=1; rec.clear();
getdis(u,0,0);
for(auto x=rec.begin();;x++){
auto y=x; ++y;
if(y==rec.end())break;
y->se=better(x->se,y->se);
}
update(u,0,0); for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v])continue;
sn=sz[v],rt=0;
getrt(v,0);
dfs(rt);
}
} void read_and_parse(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
for(int i=1;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z),add_edge(y,x,z);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
int u,r;
scanf("%d%d",&u,&r);
q[u].pb(mp(r,i));
}
}
void solve(){
sn=n,getrt(1,0);
dfs(rt);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}
int main(){
read_and_parse();
solve();
return 0;
}

【hiho1065】全图传送的更多相关文章

  1. [hihoCoder#1065]全图传送

    [hihoCoder#1065]全图传送 试题描述 先知法里奥是 Dota 系列中的一个英雄.机动性强,推塔能力一流,打钱速度快,传送技能使先知可以全地图支援.在后期比拼中通过强大的兵线控制能力使得对 ...

  2. hihoCoder Challenge 3

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

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

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

  4. 一张图解释SQL Server集群、镜像、复制、日志传送

    一张图解释SQL Server集群.镜像.复制.日志传送 本文版权归作者所有,未经作者同意不得转载.

  5. C++ 制作 json 数据 并 传送给服务端(Server) 的 php

    json数据格式,这里举个基础的例子: {"name":"LGH"} 在C++里面,我用个函数把特定的数据组合成 json void toJson(int co ...

  6. android 通过访问 php 接受 or 传送数据

    先说传送数据,可以在 利用 php 代替传送,直接把 访问的url加上 xxx.php?informatin=xxxxxx 就行了 接收的看代码吧,详细注释. 首先是 我自己定义的php 文件 < ...

  7. Linux:-拷贝或传送文件的技巧

    <---拷贝目录如何做到排除文件?常用命令cp,用法比较LOW---> tar -cf - ./* --exclude="nohup.out" | (cd /opt/ ...

  8. 关于C#调用C++ 的DLL传送字符串显示乱码的解决

    最近在做一个程序,想把某些功能用C++写成DLL供C#调用,但是在写好DLL用C#传递字符串参数时,在DLL中显示传送过来的字符串是乱码,DLL里的代码根本无法用这些字符串进行其它的处理.为此,花了一 ...

  9. 向内存0:200~0:23f依次传送数据0~3fh

    只能用字节为单位传送了. assume cs:sad sad segment start: mov ax, 20h mov ds, ax mov cx, 40h s: mov [bx], bl inc ...

随机推荐

  1. P1820 【寻找AP数】

    超级题目链接 这题程序实现其实并不难,难的是数学的思想及证明,这在真正的比赛考场上其实是不容易想到的 去年的年赛题目也是在往更难的数学思想上靠拢,并不是一味的编程,需要一定的数学基础 这个..数学性质 ...

  2. caoz的梦呓:创业公司如何做好信息安全

    猫宁!!! 参考链接:https://mp.weixin.qq.com/s/gCWjzHBRfbPFhNeg2VtFhA https://mp.weixin.qq.com/s/bmifCmD2CHV1 ...

  3. 【计算机视觉】论文笔记:Ten years of pedestrian detection, what have we learned?

    最近正在研究行人检测,学习了一篇2014年发表在ECCV上的一篇综述性的文章,是对行人检测过去十年的一个回顾,从dataset,main approaches的角度分析了近10年的40多篇论文提出的方 ...

  4. SolidWorks学习笔记6抽壳,加强筋,扫描,放样

    抽壳 概念:移除一个或者多个面,然后将其余的模型外表面向内或者向外偏移相等或者不等的距离 针对不同面设置不同厚度 方向参考 有实体的一侧是内测, 没有实体的一侧是外侧 顺序 先圆角再抽壳 加强筋. 点 ...

  5. python random 的用法

    python random的里面的方法其实是Random实例化的对象. 里面几个常用的几个方import random print( random.randint(1,10) ) # 产生 1 到 1 ...

  6. 编译FFMPEG错误对策

    在MINGW32下编译ffmpeg-2.1.1.tar.bz2 step1: ./configure   --prefix=/home/Administrator/install --extra-cf ...

  7. aws和ufile挂载数据盘EBS

    aws的话挂载的ebs需要格式化,参考:https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ebs-using-volumes.html ...

  8. splite与join

    Python split() 通过指定分隔符对字符串进行切片 切片之后为list数据类型. sentence = 'I can because I think I can ' s_1 = senten ...

  9. 【转】.NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现

    作者:Zhang_Xiang 原文地址:.NET Core + Ocelot + IdentityServer4 + Consul 基础架构实现 先决条件 关于 Ocelot 针对使用 .NET 开发 ...

  10. Luogu P5221 Product

    题目 注意一下空间限制. 令\(f(n)=\prod\limits_{i=1}^n\prod\limits_{j=1}^nij,g(n)=\prod\limits_{i=1}^n\prod\limit ...