无脑上二分+淀粉质完事了

每个子树算的时候把儿子按照最长路径从小到大依次做,和前面的单调队列算一波,每个儿子的复杂度不超过这个子树大小

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,L,R;
int fir[100010],dis[200010],nxt[200010],w[200010],id;
il vd link(int a,int b,int c){nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;}
std::vector<std::pair<int,int> >G[100010];std::vector<int>Rt[100010];
int RT;
namespace build{
bool vis[100010];
int siz[100010],f[100010],N,rt;
il vd getrt(int x,int fa=-1){
siz[x]=1;f[x]=0;
for(int i=fir[x];i;i=nxt[i]){
if(dis[i]==fa||vis[dis[i]])continue;
getrt(dis[i],x);
siz[x]+=siz[dis[i]];
f[x]=std::max(f[x],siz[dis[i]]);
}
f[x]=std::max(f[x],N-siz[x]);
if(f[x]<f[rt])rt=x;
}
int maxl[100010];il bool cmp(const std::pair<int,int>&a,const std::pair<int,int>&b){return maxl[a.first]<maxl[b.first];}
il vd dfs(int x,int fa=-1){
maxl[x]=0;
for(int i=fir[x];i;i=nxt[i]){
if(dis[i]==fa||vis[dis[i]])continue;
dfs(dis[i],x);
maxl[x]=std::max(maxl[x],maxl[dis[i]]+1);
}
}
il vd build(int x){
vis[x]=1;
for(int i=fir[x];i;i=nxt[i])if(!vis[dis[i]])G[x].push_back(std::make_pair(dis[i],w[i]));
dfs(x);
std::sort(G[x].begin(),G[x].end(),cmp);
for(int i=0;i<G[x].size();++i){
rt=0;N=siz[G[x][i].first];getrt(G[x][i].first);
Rt[x].push_back(rt);build(rt);
}
}
il vd build(){
rt=0;f[0]=1e9;N=n;getrt(1);
RT=rt;build(rt);
}
}
double mid,res;
namespace dfz{
bool vis[100010];
double f[100010],g[100010];
int que[100010],hd,tl;
int N;
bool flg;
il vd dfs(int x,int fa=-1,int len=0,double sum=0){
if(N<len)g[N=len]=sum;
else g[len]=std::max(g[len],sum);
for(int i=fir[x];i;i=nxt[i]){
if(dis[i]==fa||vis[dis[i]])continue;
dfs(dis[i],x,len+1,sum+w[i]-mid);
}
}
il vd divide(int x){
vis[x]=1;int n=0;f[0]=0;
for(int i=0;i<G[x].size();++i){
N=0;g[0]=0;dfs(G[x][i].first,x,1,G[x][i].second-mid);
hd=tl=0;
for(int j=0,p=n;j<=N;++j){
while(~p&&p+j>=L){
while((hd^tl)&&f[que[tl-1]]<f[p])--tl;
que[tl++]=p--;
}
while((hd^tl)&&que[hd]+j>R)++hd;
if((hd^tl)&&f[que[hd]]+g[j]>0){flg=1;return;}
}
for(int i=0;i<=n;++i)f[i]=std::max(f[i],g[i]);
for(int i=n+1;i<=N;++i)f[i]=g[i];
n=N;
}
for(int i=0;i<Rt[x].size();++i){
divide(Rt[x][i]);
if(flg)return;
}
}
il vd clear(){flg=0;memset(vis,0,sizeof vis);}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
n=gi(),L=gi(),R=gi();
int a,b,c;for(int i=1;i<n;++i)a=gi(),b=gi(),c=gi(),link(a,b,c),link(b,a,c);
build::build();
double l=1,r=1000000;
while(r-l>1e-4){
mid=(l+r)*0.5;
dfz::clear();
dfz::divide(RT);
if(dfz::flg)l=mid;
else r=mid;
}
l=(l+r)*0.5;printf("%.3lf\n",l);
return 0;
}

P4292 [WC2010]重建计划的更多相关文章

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

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

  2. 并不对劲的bzoj1758:p4292:[WC2010]重建计划

    题目大意 \(n\)(\(n\leq10^5\))个点的一棵树,有边权\(w\),给定\(l,r\),求边数在\([l,r]\)中的路径的平均边权的最大值 题解 二分答案,判断时将边权变成\(w-mi ...

  3. BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)

    题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...

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

    题目描述 题目传送门 分析 看到比值的形式就想到 \(01分数规划\),二分答案 设当前的值为 \(mids\) 如果存在\(\frac{\sum _{e \in S} v(e)}{|S|} \geq ...

  5. 洛谷 P4292 - [WC2010]重建计划(长链剖分+线段树)

    题面传送门 我!竟!然!独!立!A!C!了!这!道!题!incredible! 首先看到这类最大化某个分式的题目,可以套路地想到分数规划,考虑二分答案 \(mid\) 并检验是否存在合法的 \(S\) ...

  6. BZOJ1758: [Wc2010]重建计划

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

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

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

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

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

  9. bzoj 1758: [Wc2010]重建计划

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

随机推荐

  1. StretchBlt和StretchDIBits

    StretchBlt:从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩,如果目标设备是窗口DC,则意味着在窗口绘制位图,大致的使用代码如下: void DrawImag ...

  2. Java语法基础(四)----循环结构语句

    一.循环结构: 循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则 ...

  3. 如何在 Azure 门户中将托管数据磁盘附加到 Windows VM

    本文介绍了如何通过 Azure 门户将新的托管数据磁盘附加到 Windows 虚拟机. 在开始之前,请查看以下提示: 虚拟机的大小决定了可以附加多少个磁盘. 有关详细信息,请参阅虚拟机大小. 对于新磁 ...

  4. Oracle EBS INV 获取现有量等值

    DECLARE L_api_return_status VARCHAR2(1); l_qty_oh NUMBER; l_qty_res_oh NUMBER; l_qty_res NUMBER; l_q ...

  5. C#实现复制文件夹中文件到另一个文件夹的方法

    private void CopyDir(string srcPath, string aimPath) { try { // 检查目标目录是否以目录分割字符结束如果不是则添加 if (aimPath ...

  6. You are not late! You are not early!

    Do you think you are going No Where in Life? STOP! Take a deep breathe THINK! New York is three hour ...

  7. 2019 wannafly winter camp day 3

    2019 wannafly winter camp day 3 J 操作S等价于将S串取反,然后依次遍历取反后的串,每次加入新字符a,当前的串是T,那么这次操作之后的串就是TaT.这是第一次转化. 涉 ...

  8. [python]如何理解uiautomator里面的 child, child_by_text, sibling,及使用场景

    如何理解uiautomator里面的 child, child_by_text, sibling,我们借助android原生的uiautomatorviewer抓取的控件来进行理解 以如下图进行详细讲 ...

  9. table中怎么设置两行间距

    table中设置两行间距方法: css代码实现 <style> table   {   border-collapse:   separate;   border-spacing:   1 ...

  10. win10怎么更改切换输入法按键 切换输入法与Win7一样(Ctrl + 空格)

    找到电脑左下角的“开始"图标,用鼠标右键点击它,在弹出的菜单选项里再用鼠标左键点击“设置”来打开Windows设置. 进入“Windows设置”后再点击“设备” 打开“设备”界面后再点击左边 ...