这题在洛谷上可以找到提交

P2680运输计划

题目背景

公元 2044 年,人类进入了宇宙纪元。

题目描述

L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。

小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物

流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。

为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。

如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?

输入输出格式

输入格式:

输入文件名为 transport.in。

第一行包括两个正整数 n、m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。

接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 ai, bi 和 ti,表示第

i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。

接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j个 运输计划是从 uj 号星球飞往 vj 号星球。

输出格式:

输出 共1行,包含1个整数,表示小P的物流公司完成阶段性工作所需要的最短时间。

输入输出样例

输入样例#1:

6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
输出样例#1:

11

说明

n,m<=300000
这是一棵树上距离的问题
解答分两个部分:
1、求出给出各点对之间的距离
2、将一条边权减为0使得最大距离最小
树上距离一看就自然想到了【树链剖分+树状数组(或线段树)】,先树剖给点编号,然后套用树状数组结合LCA的算法求出点对距离,1问秒掉
关键是第二问,如何删。
容易想到要选的边一定在最长的路径上,但选最长路径上最长的边不一定是对的,因为第二长的边可能与第一长的边有公共边且不相差多少,但是删去了一个非公共边就错了。
看到最大最小,自然想到二分答案:
我们二分虫洞后最长的边的长度,对于每一个check(m),只需枚举所有比m大的路径,这些路径都得缩短,将这k条路径上每一条边+1,这样一来加到了k的那些边就是所有边的公共边,再看一看他们能不能通过减为0而使这k条边都小于m。
具体怎么维护每条边加了几次,用线段树?
这样二分nlognlogn的复杂度,还是不太放心
鉴于所有的询问都是单点且都在修改之后,我们可以用差分数组以O(n)的总复杂度求出
总1044ms,还是挺优秀的效率
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lbt(x) (x&-x)
using namespace std;
const int maxn=300005,INF=2000000000; inline int read(){
int out=0,flag=1;char c=getchar();
while(c<48||c>57) {if(c=='-') flag=-1;c=getchar();}
while(c>=48&&c<=57) {out=out*10+c-48;c=getchar();}
return out*flag;
} int N,M,root,rtm=INF,Maxw;
//这块是存边【链式前向星】
int head[maxn],nedge=0;
struct EDGE{
int to,w,next;
}edge[2*maxn]; inline void build(int a,int b,int w){
edge[nedge]=(EDGE){b,w,head[a]};
head[a]=nedge++;
edge[nedge]=(EDGE){a,w,head[b]};
head[b]=nedge++;
} struct node{
int a,b,w;
}p[maxn]; inline bool operator <(const node& a,const node& b){
return a.w>b.w;
}
//这块求重心
int Siz[maxn];
void dfs(int u,int f){
int to,Max=-1,Min=INF;
Siz[u]=1;
for(int k=head[u];k!=-1;k=edge[k].next)
if((to=edge[k].to)!=f){
dfs(to,u);
Siz[u]+=Siz[to];
if(Siz[to]>Max) Max=Siz[to];
else if(Siz[to]<Min) Min=Siz[to];
}
if(N-Siz[u]>Max) Max=N-Siz[u];
else if(N-Siz[u]<Min) Min=N-Siz[u];
if(Max!=-1&&Min!=INF&&Max-Min<rtm){
root=u;
rtm=Max-Min;
}
}
//这块是树链剖分
int top[maxn],siz[maxn],fa[maxn],son[maxn],id[maxn],Hash[maxn],dep[maxn],V[maxn],cnt=0; void dfs1(int u,int f,int d){
int to;
siz[u]=1;fa[u]=f;dep[u]=++d;
for(int k=head[u];k!=-1;k=edge[k].next)
if((to=edge[k].to)!=f){
dfs1(to,u,d);
V[to]=edge[k].w;
siz[u]+=siz[to];
if(!son[u]||siz[son[u]]<siz[to]) son[u]=to;
}
} void dfs2(int u,int flag){
int to;
id[u]=++cnt;Hash[cnt]=u;
flag ? top[u]=top[fa[u]]:top[u]=u;
if(son[u]) dfs2(son[u],1);
for(int k=head[u];k!=-1;k=edge[k].next)
if((to=edge[k].to)!=son[u]&&to!=fa[u])
dfs2(to,0);
}
//这块是树状数组
int A[maxn]; inline void add(int u,int v){while(u<=N){A[u]+=v;u+=lbt(u);}} inline int Sum(int u){int ans=0;while(u>0){ans+=A[u];u-=lbt(u);}return ans;} inline int Query(int l,int r){return Sum(r)-Sum(l-1);} inline void init(){for(int i=1;i<=N;i++) add(id[i],V[i]);} int solve(int u,int v){ //求路径长
int ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans+=Query(id[top[u]],id[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
return ans+Query(id[u]+1,id[v]);
} int D[maxn]; //差分数组 inline void update(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) u^=v^=u^=v;
D[id[top[u]]]+=1;
D[id[u]+1]-=1;
u=fa[top[u]];
}
if(dep[u]>dep[v]) u^=v^=u^=v;
D[id[u]+1]+=1;
D[id[v]+1]-=1;
} bool check(int m){
int tot=0,v=0;
while(p[tot+1].w>m){
++tot;
update(p[tot].a,p[tot].b);
}
for(int i=1;i<=N;i++){
v+=D[i];D[i]=0;
if(v==tot&&Maxw-V[Hash[i]]<=m){
for(int j=i+1;j<=N;j++) D[j]=0;
return true;
}
}
return false;
} int main()
{
fill(head,head+maxn,-1);
N=read();
M=read();
int a,b,w,L=0,R=0;
for(int i=1;i<N;i++){
a=read();
b=read();
w=read();
build(a,b,w);
}
dfs(1,0); //求出重心作为根
dfs1(root,0,0); //dfs1、dfs2树链剖分
dfs2(root,0);
init(); //初始化树状数组
for(int i=1;i<=M;i++){
p[i].a=read();
p[i].b=read();
p[i].w=solve(p[i].a,p[i].b);
if(p[i].w>R) R=p[i].w;
}
sort(p+1,p+1+M); //路径排个序
Maxw=R;
while(L<R){ //二分答案
int mid=(L+R)>>1;
if(check(mid)) R=mid;
else L=mid+1;
}
cout<<L<<endl;
return 0;
}

NOIP2015运输计划题解报告的更多相关文章

  1. [NOIP2015]运输计划 题解

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条 航道连通了 L 国的所有星球. 小 P 掌管一 ...

  2. 题解 [NOIP2015]运输计划

    题解 [NOIP2015]运输计划 题面 解析 首先肯定是要求出每条路径的长度. 这个用节点到根的前缀和就行了(一开始脑抽写了个线段树...) 然后有一个显然的类似贪心的想法, 就是你改造的边肯定在最 ...

  3. 运输计划(题解)(Noip2015)

    运输计划(题解)(Noip2015) 二分答案+树上差分 树上差分其实不难,只是名字高大尚,可以学一下:Eternal风度的树上差分 本人博客里也总结了一些其他的知识供大家学习:Eternal风度的博 ...

  4. NOIP2015 运输计划(bzoj4326)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 886  Solved: 574[Submit][Status] ...

  5. [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划

    [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划 试题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− ...

  6. [NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组

    [NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有 ...

  7. bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...

  8. NOIP2015 运输计划(二分+LCA+差分)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 308  Solved: 208[Submit][Status] ...

  9. 数据结构(树链剖分):COGS 2109. [NOIP2015] 运输计划

    2109. [NOIP2015] 运输计划 ★★★   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:1 s   内存限制:256 MB [题目描 ...

随机推荐

  1. 自动化运维工具saltstack03 -- 之SaltStack的数据系统

    SaltStack数据系统 saltstack有两种数据系统:grains与pillar 1.SaltStack数据系统之grains grains可以收集minion端的静态数据(即机器启动时收集一 ...

  2. 小白初识 - 计数排序(CountingSort)

    计数排序,属于桶排序特殊的一种. 当要排序n个数据的时候,如果所处的范围不大,我们可以取其中的最大值K,并将数据分散在K个桶里面, 每个桶里面的数据都是相同的(这样省去了桶内排序的时间),然后顺序取出 ...

  3. 这才是球王应有的技艺,他就是C罗

    四年一度的世界杯在本周四拉开了帷幕,俄罗斯以5:0碾压沙特阿拉伯,让我们惊呼战斗名族的强大,其后的摩洛哥VS伊朗,摩洛哥前锋布哈杜兹将足球顶入自家球门,这......咳,咳,本来是为了解围,没想到成就 ...

  4. NUMA 体系架构

    NUMA 体系架构 SMP 体系架构 NUMA 体系架构 NUMA 结构基本概念 Openstack flavor NUMA 策略 Nova 实现 NUMA 流程 1. SMP 体系架构 CPU 计算 ...

  5. Catch That Cow:BFS:加标记数组:不加标记数组

    Catch That Cow Problem Description Farmer John has been informed of the location of a fugitive cow a ...

  6. 大前端全栈CSS3移动端开发

    作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 本节课学习视频来源:https://ww ...

  7. 全国城市一卡通一级TSM平台业务架构及意义

    [导读]TSM平台是一种具有鲜明行业属性的平台,因此,各行业都建立了本行业的TSM平台.为促进城市一卡通行业移动支付的快速发展,住房和城乡建设部也建立了全国城市一卡通行业一级TSM平台. 作为住建部标 ...

  8. php json 转换

    在PHP语言中使用JSON   作者: 阮一峰 日期: 2011年1月14日 目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它. 我写过一篇<数据类型和JSON格式& ...

  9. 欢迎来怼—第二次Scrum会议

    一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华小组照片 二.开会信息 时间:2017/10/14 18:30~18:47,总计17min.地点:东北师范 ...

  10. DCOM初步窥探二

    1.COM进程透明性表现在“组件对象和客户程序可以拥有各自的空间,也可以共享同一个进程空间”. COM负责把客户的调用正确传到组件对象中,并保证参数传递的正确性. 组件对象和客户代码不必考虑调用传递的 ...