题目大意

\(n\)(\(n\leq10^5\))个点的一棵树,有边权\(w\),给定\(l,r\),求边数在\([l,r]\)中的路径的平均边权的最大值

题解

二分答案,判断时将边权变成\(w-mid\),判断是否存在一条边权总和非负且边数在[l,r]的路径

设\(f(i,j)\)表示从点\(i\)往下走\(j\)条边的边权总和最多是多少

则有\(f(i,j)=max_{v\in son(i)}\{f(v,j-1)+w(i,v)\}\)

\(ans(i)=max_{v\in son(i) , l\leq k+j+1\leq r}\{f(v,k)+f(i,j)+w(i,v)\}\)

考虑长链剖分,将\(f(i,j)\)存到\(F(i,j)=dfn[i]+j\)的位置

需要注意的是,算完点\(i\)的长儿子后,需要将\(F(i,1)\)到\(F(i,dep[i])\)的值+\(w(i,v)\)

看上去常数比点分治小,事实上。。。

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 100010
#define maxm (maxn<<1)
#define F(x,y) (dfn[x]+y)
#define inf (1e11)
#define ls (u<<1)
#define rs (u<<1|1)
#define mi (L+R>>1)
#define eps (1e-4)
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
int n,l,r,cnt,fir[maxn],nxt[maxm],v[maxm],son[maxn],fa[maxn],dfn[maxn],tim,dep[maxn];
double toso[maxn],w[maxm],tr[maxn<<2],mk[maxn<<2],ans,fakeans,mid;
inline void ade(int u1,int v1,int w1){w[cnt]=(double)w1,v[cnt]=v1,nxt[cnt]=fir[u1],fir[u1]=cnt++;}
void getdep(int u)
{
view(u,k)if(v[k]!=fa[u])
{
fa[v[k]]=u,getdep(v[k]),dep[u]=max(dep[v[k]]+1,dep[u]);
if(!son[u]||dep[v[k]]>dep[son[u]])son[u]=v[k],toso[u]=w[k];
}
}
void getdfn(int u)
{
dfn[u]=++tim;
if(son[u])getdfn(son[u]);
view(u,k)if(v[k]!=fa[u]&&v[k]!=son[u])getdfn(v[k]);
}
inline void mark(int u,double k){if(tr[u]!=-inf)mk[u]+=k,tr[u]+=k;}
inline void pd(int u){if(mk[u]==-inf){tr[ls]=tr[rs]=-inf,mk[ls]=mk[rs]=-inf,mk[u]=0;}if(mk[u]){mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}}
void add(int u,int L,int R,int x,int y,double k)
{
if(y<L||R<x||y<x)return ;
if(x<=L&&R<=y)return mark(u,k);
pd(u);
if(x<=mi)add(ls,L,mi,x,y,k);
if(y>mi)add(rs,mi+1,R,x,y,k);
tr[u]=max(tr[ls],tr[rs]);
}
void chg(int u,int L,int R,int x,double k)
{
if(x<L||R<x)return;
if(x<=L&&R<=x){tr[u]=max(tr[u],k);return;}
pd(u);
if(x<=mi)chg(ls,L,mi,x,k);
if(x>mi)chg(rs,mi+1,R,x,k);
tr[u]=max(tr[ls],tr[rs]);
}
double ask(int u,int L,int R,int x,int y)
{
if(y<L||R<x||y<x)return -inf;
if(x<=L&&R<=y)return tr[u];
pd(u);
double res=-inf;
if(x<=mi)res=ask(ls,L,mi,x,y);
if(y>mi)res=max(res,ask(rs,mi+1,R,x,y));
return res;
}
double tmp[maxn];
void getans(int u)
{
if(son[u])getans(son[u]),add(1,1,n,F(u,1),F(u,dep[u]),toso[u]-mid);
if(fakeans>=0)return;
chg(1,1,n,F(u,0),0);
int Llim=max(0,l),Rlim=min(dep[u],r);
if(Llim<=Rlim)
{
double tmp=ask(1,1,n,F(u,Llim),F(u,Rlim));
fakeans=max(fakeans,tmp);
if(fakeans>=0)return;
}
view(u,k)if(v[k]!=fa[u]&&v[k]!=son[u])
{
getans(v[k]);
if(fakeans>=0)return;
rep(i,0,dep[v[k]])
{
Llim=max(0,l-i-1),Rlim=min(r-i-1,dep[u]);
tmp[i]=ask(1,1,n,F(v[k],i),F(v[k],i))+w[k]-mid;
if(Llim<=Rlim)
{
double tmp2=ask(1,1,n,F(u,Llim),F(u,Rlim));
fakeans=max(fakeans,tmp2+tmp[i]);
if(fakeans>=0)return;
}
}
rep(i,0,dep[v[k]])chg(1,1,n,F(u,i+1),tmp[i]);
}
}
int main()
{
memset(fir,-1,sizeof(fir));
n=read(),l=read(),r=read();double L=inf,R=0;
rep(i,1,n-1){int x=read(),y=read(),z=read();ade(x,y,z),ade(y,x,z),L=min(L,(double)z),R=max(R,(double)z);}
getdep(1),getdfn(1);
while(R-L>=eps)
{
mid=(R+L)/2.0;
fakeans=-inf;tr[1]=mk[1]=-inf;
getans(1);
if(fakeans>=0)ans=max(ans,mid),L=mid+eps;
else R=mid-eps;
}
printf("%.3lf",ans);
return 0;
}
/*
4
2 3
1 2 1
1 3 2
1 4 3
*/

并不对劲的bzoj1758:p4292:[WC2010]重建计划的更多相关文章

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

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

  2. 【bzoj1758】[Wc2010]重建计划

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

  3. 【bzoj1758】 Wc2010—重建计划

    http://www.lydsy.com/JudgeOnline/problem.php?id=1758 (题目链接) 题意 给出一棵树,每条边有边权,问选出一条长度为$[L,U]$的路径,使得路径上 ...

  4. P4292 [WC2010]重建计划

    无脑上二分+淀粉质完事了 每个子树算的时候把儿子按照最长路径从小到大依次做,和前面的单调队列算一波,每个儿子的复杂度不超过这个子树大小 // luogu-judger-enable-o2 #inclu ...

  5. BZOJ1758:[WC2010]重建计划

    浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem. ...

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

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

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

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

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

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

  9. BZOJ1758: [Wc2010]重建计划

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

随机推荐

  1. 枚举型变量 ErrorStatus HSEStartUpStatus及使用

    ErrorStatus和C语言中的int .char一样,后面定义的HSEStartUpStatus是这个变量.举例,你的ErrorStatus 代表bool类型的0或者1. typedef enum ...

  2. digits

    Digits(digits.cpp/c/pas)Description给一个关于x的多项式,并给定一个x,求该多项式在带入该x时的值最后k位数字.Input第一行两个整数n.k:之后的 行,每行两个数 ...

  3. 【TFS】TFS2015链接TFS出现TF31002/TF400324问题解决方案

    安装VS2015后链接TFS发现出现TF31002错误,然后用浏览器打开TFS URL能正常访问,在TFS online中点击用vs打开按钮,提示TF400324错误 1. VS2015中打开: 2. ...

  4. 【面试 spring】【第七篇】spring的问题

    1.spring你熟悉么?两大特色 spring 主要有IOC和AOP两大特色. =========================================================== ...

  5. linux 环境 php 链接 sqlserver 2008

    说明 由于业务需要 在 linux 系统下的 PHP 环境中 要链接 sqlserver2008 数据库 . 添加PHP 链接数据库扩展 php-mssql dockerfile FROM hub.0 ...

  6. github 新建远程仓库 及 删除远程仓库

    一.新建远程仓库 1.点击 ' + ' 号 2.选择 ' new repository ' 3.填写信息  创建仓库 二.删除远程仓库 1.点击 ' Settings ' 按钮 2.滑动到最底部,点击 ...

  7. js 类继承extends

    先看例子: <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <titl ...

  8. Yii自动生成项目

      我喜欢尝试新鲜的东西.以前一直用gii生成工具,前几天突然发现用shell的方法,感觉很不错.特此总结一下yii的几个命令.   gii的工具页面: - Controller Generator ...

  9. vue class与style绑定、条件渲染、列表渲染

    列表渲染 根据我例子的需要,先来说下,列表渲染使用到的是v-for指令,需要使用 item in items 形式的特殊语法,items 是源数据数组并且 item 是数组元素迭代的别名,具体使用方法 ...

  10. JOIN ,LEFT JOIN ,ALL JOIN 等的区别和联系

    left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录  right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录 inner join(等值连接) ...