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—重建计划的更多相关文章

  1. BZOJ1758: [Wc2010]重建计划

    题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...

  2. bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race

    两题都是树分治. 1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调 ...

  3. BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP

    题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...

  4. [BZOJ1758][WC2010]重建计划(点分治+单调队列)

    点分治,对于每个分治中心,考虑求出经过它的符合长度条件的链的最大权值和. 从分治中心dfs下去取出所有链,为了防止两条链属于同一个子树,我们一个子树一个子树地处理. 用s1[i]记录目前分治中心伸下去 ...

  5. BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1758 01分数规划,所以我们对每个重心进行二分.于是问题转化为Σw[e]-mid>=0, ...

  6. BZOJ1758 WC2010 重建计划 二分答案、点分治、单调队列

    传送门 看到平均数最大,自然地想到二分答案.那么我们的$check$函数就是要求:是否存在一条长度在$[L,U]$的路径,满足其权值和$\geq 0$. 看到长度在$[L,U]$,自然地想到点分治求解 ...

  7. 2019.01.21 bzoj1758: [Wc2010]重建计划(01分数规划+长链剖分+线段树)

    传送门 长链剖分好题. 题意简述:给一棵树,问边数在[L,R][L,R][L,R]之间的路径权值和与边数之比的最大值. 思路: 用脚指头想都知道要01分数规划. 考虑怎么checkcheckcheck ...

  8. 洛谷 P4292 [WC2010]重建计划 解题报告

    P4292 [WC2010]重建计划 题目描述 \(X\)国遭受了地震的重创, 导致全国的交通近乎瘫痪,重建家园的计划迫在眉睫.\(X\)国由\(N\)个城市组成, 重建小组提出,仅需建立\(N-1\ ...

  9. [WC2010]重建计划 长链剖分

    [WC2010]重建计划 LG传送门 又一道长链剖分好题. 这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分. 如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结. 首先一看求平均值最大 ...

  10. bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

    [Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Disc ...

随机推荐

  1. Exp3

    利用不同免杀方式生成文件 1.msfvenom 使用msfvenom命令查看功能介绍 其中有: -p 选择一个载荷(或者叫模块) -l 载荷列表 -f 生成的文件格式 -e 编码方式 -l 编码次数 ...

  2. 20155339平措卓玛 Exp1 PC平台逆向破解(5)M

    20155339平措卓玛 Exp1 PC平台逆向破解(5)M 实践内容 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖 ...

  3. 【WPF】给TextBox添上Label

    原文:[WPF]给TextBox添上Label 引言     在客户端开发中,要说出现频率大的控件,必定有TextBox的身影.然而在TextBox的旁边通常得有个基友Label,形影不离.为此,我们 ...

  4. flaskr 报错及其修改

    作者:hhh5460 官网有一个flaskr的例子,按照其8个步骤(包括测试),一步一步照着做,有3个地方报错. 究其原因,可能是flaskr这个例子年代比较久远,而现在python以及flask都有 ...

  5. linux 定时器原理

    内核定时器:    unsigned long timeout = jiffies + (x * HZ);    while(1) {        // Check the condition.   ...

  6. 【2017年9月10日更新】ABP配套代码生成器(ABP Code Generator)帮助文档,实现快速开发

    ABP代码生成器介绍 ABP Code Generator 针对abp这个框架做了一个代码生成器,功能强大.分为两大功能点,一个是数据层,一个是视图层. 数据服务层:通过它,可以实现表设计.领域层初始 ...

  7. 安装Ubuntu后要做的事

    优化 删除libreoffice sudo apt-get remove libreoffice-common 删除Amazon sudo apt-get remove unity-webapps-c ...

  8. Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果

    Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果 梗概: 一. 摄像机围绕目标物体旋转, 即摄像机离目标物体有一定的距离且旋转轴心为该物体的位置. 二. 当目标物体被障碍物挡住后, 需要将摄像机 ...

  9. wordpress 5.1 后台拿shell

    闲着没事搭建了一套最新版wordpress 5.1,本身wordpress后台安全防御是比较差的,想尝试下后台是否可以拿shell. 再上传插件的地方可以直接上传php文件,并且该文件可以执行: sh ...

  10. Centos6.5下进行PHP版本升级

    http://blog.csdn.net/aliveqf/article/details/70444387