[WC2010]重建计划(分数规划+点分治+单调队列)
题目大意:给定一棵树,求一条长度在L到R的一条路径,使得边权的平均值最大。
题解
树上路径最优化问题,不难想到点分治。
如果没有长度限制,我们可以套上01分数规划的模型,让所有边权减去mid,求一条路径长度非负。
现在考虑有L和R的限制,就是我们在拼接两条路径的时候,每条路径能够匹配的是按深度排序后一段连续区间,我们只需要维护区间最大值。
然后随着深度的单调变化,这个区间在滑动,这就变成了滑动窗口问题。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 100002
#define inf 2e9
#define Re register
using namespace std;
typedef long long ll;
const double eps=1e-;
double mid,ans,ma,deep[N],man[N];
int tot,head[N],dp[N],q[N],minl,maxl,size[N],maxdeep,root,sum,n,dep[N],que[N],L,R;
bool vis[N],visit[N];
inline ll rd(){
ll x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{int n,to,l;}e[N<<];
inline void add(int u,int v,int l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;}
void getsize(int u,int fa){
size[u]=;
for(Re int i=head[u];i;i=e[i].n)if(e[i].to!=fa&&!vis[e[i].to]){
int v=e[i].to;
getsize(v,u);size[u]+=size[v];
}
}
inline int mx(int a,int b){return a>b?a:b;}
inline double maxx(double a,double b){return a>b?a:b;}
void getroot(int u,int fa){
dp[u]=;size[u]=;
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;
getroot(v,u);size[u]+=size[v];
dp[u]=mx(dp[u],size[v]);
}
dp[u]=mx(dp[u],sum-size[u]);
if(dp[u]<dp[root])root=u;
}
void getdeep(int u,int fa){
maxdeep=mx(maxdeep,dep[u]);
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;deep[v]=deep[u]+e[i].l-mid;dep[v]=dep[u]+;
getdeep(v,u);
}
}
void getcalc(int u,int fa){
man[dep[u]]=maxx(man[dep[u]],deep[u]);
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]&&e[i].to!=fa){
int v=e[i].to;getcalc(v,u);
}
}
inline bool getcheck(int u){
maxdeep=;bool tag=;
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;deep[v]=e[i].l-mid;dep[v]=;
getdeep(v,u);
int h=,t=;que[h]=v;visit[v]=;
while(h<=t){
int x=que[h++];
for(int j=head[x];j;j=e[j].n){
int v=e[j].to;
if(!vis[v]&&!visit[v]&&v!=u)que[++t]=v,visit[v]=;
}
}
int p=;L=;R=;q[++R]=;
for(Re int i=t;i>=;--i){
int x=que[i];visit[x]=;
while(p+dep[x]<maxl&&p<maxdeep){
int x=++p;
while(L<=R&&man[x]>=man[q[R]])R--;
q[++R]=x;
}
while(L<=R&&q[L]+dep[x]<minl)L++;
if(L<=R&&deep[x]+man[q[L]]>=)tag=;
}
getcalc(v,u);
}
for(Re int i=;i<=maxdeep;++i)man[i]=-inf;
return tag;
}
inline void getans(int u){
double l=ans,r=ma;
while(r-l>eps){
mid=(l+r)/2.0;
if(getcheck(u)){ans=mid;l=mid;}else r=mid;
}
}
void solve(int u){
getans(u);vis[u]=;
for(Re int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
root=n+;sum=size[v];
getroot(v,u);//getsize(root,0);
solve(root);
}
}
int main(){
n=rd();minl=rd();maxl=rd();int u,v,w;
for(int i=;i<=n;++i)man[i]=-inf;
ma=-1e9;ans=1e9;
for(Re int i=;i<n;++i){
u=rd();v=rd();w=rd();ma=maxx(ma,(double)w);ans=min(ans,(double)w);
add(u,v,w);add(v,u,w);
}
dp[root=n+]=n;sum=n;
getroot(,);//getsize(root,0);
solve(root);
printf("%.3lf",ans);
return ;
}
[WC2010]重建计划(分数规划+点分治+单调队列)的更多相关文章
- bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check
[Wc2010]重建计划 Time Limit: 40 Sec Memory Limit: 162 MBSubmit: 4345 Solved: 1054[Submit][Status][Disc ...
- BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...
- 【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列
一开始看到$\frac{\sum_{}}{\sum_{}}$就想到了01分数规划但最终还是看了题解 二分完后的点分治,只需要维护一个由之前处理过的子树得出的$tb数组$,然后根据遍历每个当前的子树上的 ...
- BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1758 01分数规划,所以我们对每个重心进行二分.于是问题转化为Σw[e]-mid>=0, ...
- BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)
题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...
- BZOJ 1758: [Wc2010]重建计划 01分数规划+点分治+单调队列
code: #include <bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in", ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- BZOJ1758: [Wc2010]重建计划
题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...
- 洛谷 P4292 [WC2010]重建计划 解题报告
P4292 [WC2010]重建计划 题目描述 \(X\)国遭受了地震的重创, 导致全国的交通近乎瘫痪,重建家园的计划迫在眉睫.\(X\)国由\(N\)个城市组成, 重建小组提出,仅需建立\(N-1\ ...
随机推荐
- 2019省赛训练组队赛3.31周四-17fj
https://vjudge.net/contest/289558#overview A - Frog Therearex frogs and y chicken in a garden. Kim f ...
- 使用node写一个简单的页面操作
let http = require('http'); let urlStr = require('url'); let fs = require('fs'); let path = require( ...
- 对B+树,B树,红黑树的理解
出处:https://www.jianshu.com/p/86a1fd2d7406 写在前面,好像不同的教材对b树,b-树的定义不一样.我就不纠结这个到底是叫b-树还是b-树了. 如图所示,区别有以下 ...
- Azure系列2.1.9 —— CloudBlob
(小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...
- 剑指offer(10)
题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 思路: 如果忽略题目中 ...
- Python——tkinter操作
一.创建单选框 form tkinter import * #创建窗口体 window = tk() #初始化组合件绑定 w1 = IntVar() #设置初始选择项1 w1.set(1) def O ...
- ES 6 系列 - Module 的语法
es 6 大幅度优化了模块化编程的规范. 写在前面:在 es6 之前,说起 js 的模块化,一般都避不开 CommonJs 和 AMD 两种方案.这两种方案,前者应用于服务器,后者应用于浏览器.而 e ...
- WPF中如何调整TabControl的大小,使其跟随Window的大小而改变?
多年不写技术博客,手生的很,也不知道大家都关注什么,最近在研究Wpf及3d模型的展示,碰到很多问题,这个是最后一个问题,写出来小结一下...... WPF中如何调整TabControl的大小,使其跟随 ...
- User Authentication with Angular and ASP.NET Core
User authentication is a fundamental part of any meaningful application. Unfortunately, implementing ...
- UVA 1602 Lattice Animals
题目 输入n.w.h($1\leqslant n \leqslant 10, 1\leqslant w,h \leqslant n$),求能放在w*h网格里的不同的n连块的个数(注意,平移.旋转.翻转 ...