【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 ...
随机推荐
- Django:admin后台汉化问题
1.设置admin站点中文显示,即汉化admin后台管理站点. 方法一:修改settings文件 LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' 更改为: LANG ...
- 20155308《网络对抗》Exp8 Web基础
20155308<网络对抗>Exp8 Web基础 实践原理与实践说明 本实践的具体要求有: (1).Web前端HTML 能正常安装.启停Apache.理解HTML,理解表单,理解GET与P ...
- NetWork——描述一次完整的网络请求过程
台根DNS,根DNS服务器收到请求后会返回负责这个域名(.net)的服务器的一个IP,本地DNS服务器使用该IP信息联系负责.net域的这台服务器.这台负责.net域的服务器收到请求后,如果自己无法解 ...
- 【php增删改查实例】第五节 - easyUI的基本使用
1. 列表组件 datagrid 1.1 创建一个grid.html <html> <head> <meta charset="utf-8" /> ...
- C# List left join
public class Test1 { public int ID { get; set; } public string Name { get; set; } } public class Tes ...
- github添加ssh连接用户
最近打算用flask写一个自己的博客网站,打算把代码放在GitHub上,使用ssh访问.记录下GitHub配置ssh用户的流程. 1.在本地电脑或云服务器上生成ssh公钥和私钥,window下可以进入 ...
- cocos2d-x学习之路(二)——分析AppDelegate和HelloWorldScene文件
这里我们来看一下cocos自动给我们生成的工程里有些什么东西,并且分析一下这些代码的用途,来为我们以后编写cocos程序铺下基础. 这里我建议看我这份随笔的看官先看看cocos官网的快速入门手册,不然 ...
- C++ string 类详解
字符串是存储在内存的连续字节中的一系列字符.C++ 处理字符串的方式有两种,一种来自 C 语言,常被称为 C-风格字符串,另一种是基于 string 类库的字符串处理方式.C 风格字符串的处理可以参考 ...
- Python能做什么?
Python作为一个功能强大,并且简单易学的编程语言而广受好评,那么Python都能做些什么呢?概括起来有以下几个方面: 1.Web开发: 2.大数据处理: 3.人工智能: 4.自动化运维: 5.云计 ...
- PHP Laravel Install and Quickstart
1.安装Laravel 一键安装包Laravel 要安装Laravel依赖的PHP7以上版本,以及php 扩展php-openssl php-pdo ... 以及Homestead github下载安 ...