传送门

长链剖分好题。

题意简述:给一棵树,问边数在[L,R][L,R][L,R]之间的路径权值和与边数之比的最大值。


思路:

用脚指头想都知道要01分数规划。

考虑怎么checkcheckcheck。

发现就是求在转化成真·边权之后有没有长度在[L,R][L,R][L,R]之间的路径权值是大于0的。

然后可以设计状态fi,jf_{i,j}fi,j​表示iii开头长度为jjj的路径最大值,这个可以用长链剖分优化转移。

然后考虑怎么把经过iii的两条路径拼起来更新答案,这个可以用线段树优化转移,然后做完了。

代码:

  1. #include<bits/stdc++.h>
  2. #define fi first
  3. #define se second
  4. #define ri register int
  5. using namespace std;
  6. inline int read(){
  7. int ans=0;
  8. char ch=getchar();
  9. while(!isdigit(ch))ch=getchar();
  10. while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
  11. return ans;
  12. }
  13. const double eps=1e-4,inf=1e18;
  14. const int N=1e5+5;
  15. int n,len[N],fa[N],hson[N],tot=0,mxdep[N],dep[N],pos[N],num[N],D,U;
  16. typedef pair<int,double> pii;
  17. vector<pii>e[N];
  18. struct edge{int u,v,w;}G[N];
  19. double ans,f[N];
  20. struct segement_tree{
  21. #define lc (p<<1)
  22. #define rc (p<<1|1)
  23. #define mid (l+r>>1)
  24. double mx[N<<2];
  25. inline void pushup(int p){mx[p]=max(mx[lc],mx[rc]);}
  26. inline void build(int p,int l,int r){
  27. mx[p]=-inf;
  28. if(l==r){pos[l]=p;return;}
  29. build(lc,l,mid),build(rc,mid+1,r);
  30. }
  31. inline void update(int p,int l,int r,int k,double v){
  32. if(l==r){mx[p]=max(mx[p],v);return;}
  33. k<=mid?update(lc,l,mid,k,v):update(rc,mid+1,r,k,v),pushup(p);
  34. }
  35. inline double query(int p,int l,int r,int ql,int qr){
  36. if(ql>r||qr<l)return -inf;
  37. if(ql<=l&&r<=qr)return mx[p];
  38. if(qr<=mid)return query(lc,l,mid,ql,qr);
  39. if(ql>mid)return query(rc,mid+1,r,ql,qr);
  40. return max(query(lc,l,mid,ql,mid),query(rc,mid+1,r,mid+1,qr));
  41. }
  42. }T;
  43. void dfs1(int p){
  44. for(ri i=0,v;i<e[p].size();++i){
  45. if((v=e[p][i].fi)==fa[p])continue;
  46. fa[v]=p,dep[v]=mxdep[v]=dep[p]+1,dfs1(v),mxdep[p]=max(mxdep[p],mxdep[v]);
  47. if(mxdep[p]==mxdep[v])hson[p]=v;
  48. }
  49. len[p]=mxdep[p]-dep[p];
  50. }
  51. void dfs2(int p){
  52. num[p]=++tot;
  53. if(!hson[p])return;
  54. dfs2(hson[p]);
  55. for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i].fi)!=fa[p]&&v!=hson[p])dfs2(v);
  56. }
  57. void solve(int p,double dist){
  58. T.update(1,1,n,num[p],dist);
  59. for(ri i=0;i<e[p].size();++i)if(e[p][i].fi==hson[p]){solve(hson[p],dist+e[p][i].se);break;}
  60. for(ri i=0,v;i<e[p].size();++i){
  61. if((v=e[p][i].fi)==fa[p]||v==hson[p])continue;
  62. solve(v,dist+e[p][i].se);
  63. for(ri j=1;j<=mxdep[v]-dep[p];++j){
  64. f[j]=T.mx[pos[num[v]+j-1]];
  65. if(j<=U){
  66. double tmp=T.query(1,1,n,max(1,num[p]+D-j),min(num[p]+U-j,num[p]+len[p]));
  67. ans=max(ans,tmp+f[j]-2*dist);
  68. }
  69. }
  70. for(ri j=1;j<=mxdep[v]-dep[p];++j)T.update(1,1,n,num[p]+j,f[j]);
  71. }
  72. ans=max(ans,T.query(1,1,n,num[p]+D,min(num[p]+U,num[p]+len[p]))-dist);
  73. }
  74. inline bool check(double tmp){
  75. ans=-inf,T.build(1,1,n);
  76. for(ri i=1;i<=n;++i)e[i].clear();
  77. for(ri i=1,u,v;i<n;++i){
  78. u=G[i].u,v=G[i].v;
  79. double w=G[i].w-tmp;
  80. e[u].push_back(pii(v,w)),e[v].push_back(pii(u,w));
  81. }
  82. return solve(1,0),ans>=-eps;
  83. }
  84. int main(){
  85. n=read(),D=read(),U=read();
  86. double L=inf,R=0;
  87. for(ri i=1;i<n;++i){
  88. G[i].u=read(),G[i].v=read(),G[i].w=read(),L=min(L,(double)G[i].w),R=max(R,(double)G[i].w);
  89. e[G[i].u].push_back(pii(G[i].v,0)),e[G[i].v].push_back(pii(G[i].u,0));
  90. }
  91. dfs1(1),dfs2(1);
  92. while(R-L>=eps){
  93. double Mid=(L+R)/2;
  94. if(check(Mid))L=Mid;
  95. else R=Mid;
  96. }
  97. printf("%.3lf",L);
  98. return 0;
  99. }

2019.01.21 bzoj1758: [Wc2010]重建计划(01分数规划+长链剖分+线段树)的更多相关文章

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

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

  2. 2019.03.11 COGS2652 秘术(天文密葬法)(分数规划+长链剖分)

    传送门 题意:nnn个点的树,每个点两个值a,ba,ba,b,问长度为mmm的路径∑ai∑bi\frac{\sum a_i}{\sum b_i}∑bi​∑ai​​的最大值. 思路:一眼要01分数规划, ...

  3. BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)

    题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...

  4. [WC2010]重建计划(长链剖分+线段树+分数规划)

    看到平均值一眼分数规划,二分答案mid,边权变为w[i]-mid,看是否有长度在[L,R]的正权路径.设f[i][j]表示以i为根向下j步最长路径,用长链剖分可以优化到O(1),查询答案线段树即可,复 ...

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

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

  6. P4292-[WC2010]重建计划【长链剖分,线段树,0/1分数规划】

    正题 题目链接:https://www.luogu.com.cn/problem/P4292 题目大意 给出\(n\)个点的一棵树,然后求长度在\([L,U]\)之间的一条路径的平均权值最大. 解题思 ...

  7. BZOJ1758: [Wc2010]重建计划

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

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

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

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

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

随机推荐

  1. Android 中Application向Activity 传递数值

    比如极光注册时获取用户的唯一标示ID需要在登录时进行传递,实现消息的指定用户推送功能 public String id; public String getId() { return id; } pu ...

  2. chrome谷歌浏览器常用快捷键搜集整理

    搜集了下面比较实用的快捷键,部分不好操作的组合键就不写了:Ctrl+N:打开新窗口. Ctrl+T:打开新标签页.Ctrl+W:关闭当前标签Alt+F4:关闭chrome浏览器Ctrl+Tab:切换到 ...

  3. js常用的数组,,字符串,,Math..正则方法

    数组 slice[start,end] 返回从原数组中指定开始下标到结束下标之间的项目组成新数组(不会影响原数组) splice() 1.删除功能:2个参数 , 起始位置 , 删除的项目 2.插入功能 ...

  4. 【C++】:STL迭代器使用---[容器::iterator iter;]

    参考文章:http://blog.csdn.net/qq_23100787/article/details/51388163 迭代器这种东西,就是为了使访问简单!! 容器::iterator iter ...

  5. Django中反向生成models

    我们在展示django ORM反向生成之前,我们先说一下怎么样正向生成代码. 正向生成,指的是先创建model.py文件,然后通过django内置的编译器,在数据库如mysql中创建出符合model. ...

  6. sqlserver使用SQL语句创建数据库登录对象、数据库用户以及对为该用户赋予操作权限

    --创建登录名USE masterGO--PbMaster,密码123456CREATE LOGIN PbMaster with PASSWORD='1234GO --创建数据库用户USE E_Mar ...

  7. Ado.net简单快捷帮助类

    using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; usin ...

  8. VS2013中Nuget程序包管理器控制台使用入门(二)-如何使用Nuget提供的帮助(原创)

    如何使用Nuget提供的帮助? 1.从get-help Nuget开始,键入“get-help NuGet”以查看所有可用的 NuGet 命令. 用法: PM> get-help Nuget 主 ...

  9. Navicat premiu的导入和导出

    对于Navicat premiu(数据库管理工具)中对于数据库的导出和导入步骤如下: 1.选择要导出的数据库->转储SQL文件->选择结构和数据或结构->选择存放的路径,即可导出成功 ...

  10. c#一个统计运行时间方法

    public string STD(int HowManySecond) { ) { "; } string ShowStr = ""; * )) { ShowStr + ...