Luogu P2680 运输计划(二分+树上差分)
题意
题目背景
公元\(2044\)年,人类进入了宇宙纪元。
题目描述
公元\(2044\)年,人类进入了宇宙纪元。
\(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星球之间,这\(n-1\)条航道连通了\(L\)国的所有星球。
小\(P\)掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从\(u_i\)号星球沿最快的宇航路径飞行到\(v_i\)号星球去。显然,飞船驶过一条航道是需要时间的,对于航道\(j\),任意飞船驶过它所花费的时间为\(t_j\),并且任意两艘飞船之间不会产生任何干扰。
为了鼓励科技创新,\(L\)国国王同意小\(P\)的物流公司参与\(L\)国的航道建设,即允许小\(P\)把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小\(P\)的物流公司就预接了\(m\)个运输计划。在虫洞建设完成后,这\(m\)个运输计划会同时开始,所有飞船一起出发。当这\(m\)个运输计划都完成时,小\(P\)的物流公司的阶段性工作就完成了。
如果小\(P\)可以自由选择将哪一条航道改造成虫洞,试求出小\(P\)的物流公司完成阶段性工作所需要的最短时间是多少?
输入输出格式
输入格式:
第一行包括两个正整数\(n, m\),表示\(L\)国中星球的数量及小\(P\)公司预接的运输计划的数量,星球从\(1\)到\(n\)编号。
接下来\(n-1\)行描述航道的建设情况,其中第\(i\)行包含三个整数\(a_i,b_i\)和\(t_i\),表示第\(i\)条双向航道修建在\(a_i\)与\(b_i\)两个星球之间,任意飞船驶过它所花费的时间为\(t_i\)。数据保证\(1 \leq a_i,b_i \leq n\)且\(0 \leq t_i \leq 1000\)。
接下来\(m\)行描述运输计划的情况,其中第\(j\)行包含两个正整数\(u_j\)和\(v_j\),表示第\(j\)个运输计划是从\(u_j\)号星球飞往\(v_j\)号星球。数据保证\(1 \leq u_i,v_i \leq n\)。
输出格式:
一个整数,表示小\(P\)的物流公司完成阶段性工作所需要的最短时间。
输入输出样例
输入样例:
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
输出样例:
11
说明
所有测试数据的范围和特点如下表所示
思路
树上差分板子题,要不你试试? --logeadd
过了一个月终于把它试出来了...
首先对于答案我们来二分,二分的左区间为\(0\)(当然,最优的左区间并不是\(0\)),有区间为最长的运输计划的长度。
运输区间的长度可以用\(O( \log ^2 n)\)的树链剖分或者\(O( \log n)\)的倍增算法(按照这题的数据强度的话后者显然更可过),可是我们如何判定二分出的答案是否可行呢?
首先处理出长度超过二分答案的边的数量\(sum\),然后从根跑一边\(dfs\),统计每个结点下的每一子树中有多少点在计划中会走到该子树的根结点。如果该值为\(sum\),则用这条边更新最大边权,最后直接看最长计划长度减去最大边权是否小于二分答案即可。
现在又有问题了:如何快速统计呢?这就需要树上差分了。对于每一个计划我们把它看成两个部分:从\(u\)到\(LCA(u,v)\)和从\(LCA(u,v)\)到\(v\),我们再不妨把所有分出的部分都看成向上运输的计划,即把它看成这样的两部分:从\(u\)到\(LCA(u,v)\)和从\(v\)到\(LCA(u,v)\)。然后在树上统计每一结点作为计划开头的次数,记为正数;统计每一结点作为结尾的次数,记为负数。
那么按照上面\(dfs\)的思路,我们就可以这么写:
int dfs2(int now)//先看下面那个函数
{
int re=0;//该结点信息
for(register int i=top[now];i;i=nex[i])
{
if(to[i]==fa[now][0]) continue;
int lzq=dfs2(to[i]);//该结点下的子树信息,
re+=lzq;
if(lzq==sum&&len[i]>tmp) tmp=len[i];//如果刚好有sum条边,更新答案
}
return re+js[now];
}
inline bool check(int now)//二分出的答案为now
{
memset(js,0,sizeof js);//结点作为计划开头的次数计数
tmp=-0x3f3f3f3f,sum=0;//sum记录需要减少时间的计划数量,tmp记录有sum条边同时经过的边的最大长度
for(register int i=0;i<m;i++) if(tim[i]>now) sum++,js[u[i]]++,js[v[i]]++,js[st[i]]-=2;//计数统计
dfs2(1);//开始dfs
return max_time-tmp<=now;//判断最大时间的一个计划的时间是否可减少至now
}
AC代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
int n,m,u[MAXN],v[MAXN],st[MAXN],tim[MAXN];
int cnt,top[MAXN],to[MAXN<<1],len[MAXN<<1],nex[MAXN<<1];
int dep[MAXN],dis[MAXN],fa[MAXN][20];
int L,R,ans,max_time,tmp,sum,js[MAXN];
inline int read()
{
int re=0;
char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
return re;
}
void dfs1(int now)
{
for(register int i=1;i<=19;i++) fa[now][i]=fa[fa[now][i-1]][i-1];
for(register int i=top[now];i;i=nex[i])
{
if(to[i]==fa[now][0]) continue;
dis[to[i]]=dis[now]+len[i],dep[to[i]]=dep[now]+1,fa[to[i]][0]=now;
dfs1(to[i]);
}
}
int dfs2(int now)
{
int re=0;
for(register int i=top[now];i;i=nex[i])
{
if(to[i]==fa[now][0]) continue;
int lzq=dfs2(to[i]);
re+=lzq;
if(lzq==sum&&len[i]>tmp) tmp=len[i];
}
return re+js[now];
}
inline int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(register int i=19;i>=0;i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(register int i=19;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
inline bool check(int now)
{
memset(js,0,sizeof js);
tmp=-0x3f3f3f3f,sum=0;
for(register int i=0;i<m;i++) if(tim[i]>now) sum++,js[u[i]]++,js[v[i]]++,js[st[i]]-=2;
dfs2(1);
return max_time-tmp<=now;
}
int main()
{
n=read(),m=read();
for(register int i=0;i<n-1;i++)
{
int x=read(),y=read(),z=read();
to[++cnt]=y,len[cnt]=z,nex[cnt]=top[x],top[x]=cnt;
to[++cnt]=x,len[cnt]=z,nex[cnt]=top[y],top[y]=cnt;
}
dep[1]=1;
dfs1(1);
for(register int i=0;i<m;i++)
{
u[i]=read(),v[i]=read(),st[i]=LCA(u[i],v[i]);
tim[i]=dis[u[i]]-dis[st[i]]+dis[v[i]]-dis[st[i]];
if(tim[i]>max_time) max_time=tim[i];
}
L=0,R=max_time;
while(L<=R)
{
int mid=(L+R)>>1;
if(check(mid)) ans=mid,R=mid-1;
else L=mid+1;
}
printf("%d",ans);
return 0;
}
Luogu P2680 运输计划(二分+树上差分)的更多相关文章
- 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)
P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...
- P2680 运输计划 二分+树上差分
又咕咕了几天\(QwQ\) 思路:二分+树上差分 提交:\(\geq5\)次 错因:\(lca\)写错+卡了很久常数(哪位大佬帮我康康,有更好的写法请指出\(QwQ\)) 题解: 我们先将原问题转化为 ...
- [luogu]P2680 运输计划[二分答案][树上差分]
[luogu]P2680 [NOIP2015]运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n ...
- luogu P2680 运输计划 (二分答案+树上差分)
题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...
- 洛谷P2680 运输计划(树上差分+二分)
传送门 考虑树上乱搞 首先这是满足二分性质的,如果在某个时间可以完成工作那么比他更长的时间肯定也能完成工作 然后考虑二分,设当前答案为$mid$,如果有一条链的长度大于$mid$,那么这条链上必须得删 ...
- BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1930 Solved: 1231[Submit][Statu ...
- NOIP2015Day2T3运输计划(二分+树上差分)
做了这么多NOIPTG的题,这是唯一 一道一眼秒的T3(有时候T2还不会做QAQ)... 题目大意就不说了QWQ 思路大概是:啊最大值最小化,来个二分.检验mid的话,显然就是用最长路径减去所有边权& ...
- 【Luogu】P2680运输计划(树上差分+二分)
题目链接 总体思路……怎么说呢……是个暴力吧…… 首先用倍增预处理出每条路径的长度. 然后按长度把路径排序. 然后二分答案.对于当前答案mid检验,怎么检验呢? 首先差分把所有长度比mid大的链上除了 ...
- P2680 运输计划[二分+LCA+树上差分]
题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间,这 n-1n−1 条航道连通了 LL 国的所有星球. 小 ...
随机推荐
- 类欧几里德算法(洛谷 P5170
#include <iostream> #include <cstdio> #include <queue> #include <algorithm> ...
- 时间复杂度 - Convert 计算次数 TO 时间复杂度
我们假设计算机运行一行基础代码需要执行一次运算. int aFunc(void) { printf("Hello, World!\n"); // 需要执行 1 次 return 0 ...
- LUOGU P4281 [AHOI2008]紧急集合 / 聚会 (lca)
传送门 解题思路 可以通过手玩或打表发现,其实要选的点一定是他们三个两两配对后其中一对的$lca$上,那么就直接算出来所有的$lca$,比较大小就行了. #include<iostream> ...
- poj3167- Cow Patterns
传送门 两个串相等定义为串中每一位排序后的相对大小相等. 一位相等等价于这一位前面比他小的和等于他的数的个数相等. 那么用kmp,比较的时候比较这两个个数就可以了. 一开始很瓜地想,询问一段区间内比我 ...
- js图片预加载实现!
var myImage = (function(){ var imgNode = document.createElement( 'img' ); document.body.appendChild( ...
- Windows安全证书生成方法(开发者证书)
首先,查看本机安装的证书可在“运行”中输入:certmgr.msc 一.win8.8.1.win10系统,使用管理员powershell创建证书: (1)利用如下命令来创建证书并获取到其指纹 New- ...
- System.Web.Mvc.FileStreamResult.cs
ylbtech-System.Web.Mvc.FileStreamResult.cs 1.程序集 System.Web.Mvc, Version=5.2.3.0, Culture=neutral, P ...
- Android基础控件TextClock和Chronometer的使用
1.简介 DigitalClock, TextClock,AnalogClock,Chronometer其中DigitalClock和AnalogClock废弃了! TextClock是在Androi ...
- elasticDump的安装使用
官方地址:官方地址:https://github.com/taskrabbit/elasticsearch-dump 安装方式如下:安装NodeJS下载源码:wget http://nodejs.or ...
- 2019牛客暑假多校赛(第二场) F和H(单调栈)
F-Partition problem https://ac.nowcoder.com/acm/contest/882/F 题意:输入一个数n,代表总共有2n个人,然后每个人对所有人有个贡献值,然后问 ...