【bzoj1758】 Wc2010—重建计划
http://www.lydsy.com/JudgeOnline/problem.php?id=1758 (题目链接)
题意
给出一棵树,每条边有边权,问选出一条长度为$[L,U]$的路径,使得路径上的边权平均数最大是多少。
Solution
哈哈,爸爸终于过啦。
首先二分答案,然后路径统计显然点分治,统计答案的时候单调队列维护一下滑动窗口里面的最值。因为要点分治若干次,我们不妨将重心预处理出来,减少常数。
一定要小心,在点分治处理子树的时候,一定要按照深度从小到大的顺序处理,不然直接被新加的那组扫把型的数据卡掉T_T。
细节
清空cnt。
代码
// bzoj1758
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define LD long double
#define eps 1e-4
#define inf (1ll<<60)
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=100010;
int n,m,U,L,cnt,head[maxn];
struct edge {int to,next,w;}e[maxn<<1];
struct data {
int num,D;
friend bool operator < (data a,data b) {return a.D>b.D;}
}; namespace NodeDivide {
int Dargen,rt,D,maxD,sum,size[maxn],vis[maxn],Sum[maxn],f[maxn],q[maxn],h[maxn];
edge t[maxn];
double ans,deep[maxn],dis[maxn],Dis[maxn];
void link(int u,int v) {t[++cnt]=(edge){v,h[u]};h[u]=cnt;}
void dfs(int x,int fa) {
size[x]=f[x]=1;
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && !vis[e[i].to]) {
dfs(e[i].to,x);
f[x]=max(f[x],size[e[i].to]);
size[x]+=size[e[i].to];
}
f[x]=max(f[x],sum-size[x]);
if (f[x]<f[rt]) rt=x;
}
void caldeep(int x,int fa,int d) {
D=max(D,d);
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && !vis[e[i].to]) {
deep[e[i].to]=deep[x]+e[i].w;
caldeep(e[i].to,x,d+1);
}
}
void caldis(int x,int fa,int d) {
dis[d]=max(dis[d],deep[x]);
for (int i=head[x];i;i=e[i].next)
if (e[i].to!=fa && !vis[e[i].to]) caldis(e[i].to,x,d+1);
}
void solve(int x,double res) {
vis[x]=1;maxD=0;
priority_queue<data> T;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
D=0;deep[e[i].to]=e[i].w;
caldeep(e[i].to,x,1);
T.push((data){e[i].to,D});
}
while (!T.empty()) {
data tmp=T.top();T.pop();
caldis(tmp.num,x,1);
int l=1,r=0,pl=maxD,pr=maxD;
for (int i=1;i<=tmp.D;i++) {
for (;pl>-1 && pl>=L-i;pl--) {
while (l<=r && Dis[q[r]]-q[r]*res<Dis[pl]-pl*res) r--;
q[++r]=pl;
}
for (;pr>-1 && pr>U-i;pr--) while (l<=r && q[l]>=pr) l++;
if (pl<pr) ans=max(ans,dis[i]-i*res+Dis[q[l]]-q[l]*res);
}
maxD=max(maxD,tmp.D);
for (int i=1;i<=tmp.D;i++) Dis[i]=max(Dis[i],dis[i]),dis[i]=0;
}
for (int i=1;i<=maxD;i++) Dis[i]=0;
for (int i=h[x];i;i=t[i].next) if (Sum[t[i].to]>=L) solve(t[i].to,res);
vis[x]=0;
}
void caldargen(int x,int fa) {
vis[x]=1;
if (fa) link(fa,x);else Dargen=x;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
sum=size[e[i].to],rt=0;
dfs(e[i].to,x);
Sum[rt]=sum;
caldargen(rt,x);
}
vis[x]=0;
}
void Init() {
cnt=0;
sum=n;f[rt=0]=1<<30;
dfs(1,0);Sum[rt]=sum;
caldargen(rt,0);
}
double main(double res) {
ans=-inf;
solve(Dargen,res);
return ans;
}
}
using namespace NodeDivide; void link(int u,int v,int w) {
e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
e[++cnt]=(edge){u,head[v],w};head[v]=cnt;
}
int main() {
scanf("%d%d%d",&n,&L,&U);
for (int u,v,w,i=1;i<n;i++) {
scanf("%d%d%d",&u,&v,&w);
link(u,v,w);
}
Init();
double l=0,r=1000000,ans;
while (l<=r) {
double mid=(l+r)/2;
if (main(mid)>=0) l=mid+eps,ans=mid;
else r=mid-eps;
}
printf("%.3lf",ans);
return 0;
}
【bzoj1758】 Wc2010—重建计划的更多相关文章
- BZOJ1758: [Wc2010]重建计划
题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...
- bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race
两题都是树分治. 1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调 ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- [BZOJ1758][WC2010]重建计划(点分治+单调队列)
点分治,对于每个分治中心,考虑求出经过它的符合长度条件的链的最大权值和. 从分治中心dfs下去取出所有链,为了防止两条链属于同一个子树,我们一个子树一个子树地处理. 用s1[i]记录目前分治中心伸下去 ...
- BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1758 01分数规划,所以我们对每个重心进行二分.于是问题转化为Σw[e]-mid>=0, ...
- BZOJ1758 WC2010 重建计划 二分答案、点分治、单调队列
传送门 看到平均数最大,自然地想到二分答案.那么我们的$check$函数就是要求:是否存在一条长度在$[L,U]$的路径,满足其权值和$\geq 0$. 看到长度在$[L,U]$,自然地想到点分治求解 ...
- 2019.01.21 bzoj1758: [Wc2010]重建计划(01分数规划+长链剖分+线段树)
传送门 长链剖分好题. 题意简述:给一棵树,问边数在[L,R][L,R][L,R]之间的路径权值和与边数之比的最大值. 思路: 用脚指头想都知道要01分数规划. 考虑怎么checkcheckcheck ...
- 洛谷 P4292 [WC2010]重建计划 解题报告
P4292 [WC2010]重建计划 题目描述 \(X\)国遭受了地震的重创, 导致全国的交通近乎瘫痪,重建家园的计划迫在眉睫.\(X\)国由\(N\)个城市组成, 重建小组提出,仅需建立\(N-1\ ...
- [WC2010]重建计划 长链剖分
[WC2010]重建计划 LG传送门 又一道长链剖分好题. 这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分. 如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结. 首先一看求平均值最大 ...
- bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check
[Wc2010]重建计划 Time Limit: 40 Sec Memory Limit: 162 MBSubmit: 4345 Solved: 1054[Submit][Status][Disc ...
随机推荐
- java web classpath
在使用ssh等框架开发web程序时配置文件(xml和properties)存放的路径一般为src下,当部署程序时则必须存在于classes路径下,具体如下 src不是classpath, WEB-IN ...
- 20155337 《网络对抗》 Exp2 后门原理与实践
20155337 <网络对抗> Exp2 后门原理与实践 一.基础问题回答 - 例举你能想到的一个后门进入到你系统中的可能方式? 在Unix里,login程序通常用来对telnet来的用户 ...
- linux 定时器原理
内核定时器: unsigned long timeout = jiffies + (x * HZ); while(1) { // Check the condition. ...
- eclipse 最最最常用快捷键
使用eclipse这么久,发现其跟PS一样,使用一些快捷键会有效率很多. 至此总结出以下每次打开eclipse基本都会用上的快捷键. 不熟悉这些快捷键,在实际编程中有意识使用的话对以后编码很有帮助. ...
- centos7 安装 telnet
https://blog.csdn.net/wfh6732/article/details/55062016/ https://blog.csdn.net/typa01_kk/article/deta ...
- 苹果电脑获取Android Studio的发布版SHA1和开发版SHA1
最近开始转战安卓,准备把我在苹果上的应用也在安卓上来一波,其中就遇到一个问题就是最牛天气(iOS和微信小程序都已经有了,就差安卓的了)引用的百度的定位功能,需要填写发布版SHA1和开发版SHA1,作为 ...
- 软件测试为何我会首选Python
对于软件测试选择什么样的语言去学习,不同的人有不同的回答,为什么我会首选Python呢?这就要从Python的特点与适应领域说了. 一.Python的特点:优雅.明确.简单. 二.Python适合的领 ...
- 5分钟让你明白HTTP协议
一.HTTP简介 1.http协议介绍 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标 ...
- 运用fancybox弹出div的方式弹出视频界面
fancybox可以弹出很多窗体,甚至一个swf格式的小视频.但这样的swf视频播放的时候并没有任何的控件.只能重头看到尾,或者关闭.我们可以利用fancybox弹出div盒子的方式配合html5很快 ...
- python matploblib学习笔记
import matplotlib.pyplot as pltimport numpy as np # matplotlib画图注释中文需要设置from matplotlib.font_manager ...