【BZOJ1758】【WC2010】重建计划(点分治,单调队列)

题面

BZOJ

洛谷

Description

Input

第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N进行标号

Output

输出最大平均估值,保留三位小数

Sample Input

4

2 3

1 2 1

1 3 2

1 4 3

Sample Output

2.500

HINT

N<=100000,1<=L<=U<=N-1,Vi<=1000000

题解

我这鬼代码在BZOJ上跑不过去

因为\(BZOJ\)添加了一组很鬼畜的数据,导致\(BZOJ\)上会\(TLE\)

洛谷上能过。

表示完全不会点分治了,这道题目就当复习用。

每次我们二分一个答案,将所有的边权全部减去这个二分的值

此时题目相当于询问是否存在一条边数在\([L,U]\)之间,权值和大于\(0\)的路径。

考虑每个分治重心的贡献,依次计算当前重心的每一棵子树,

求出所有点的深度(经过的边数),以及权值和

对于每个深度,维护一个前面所有子树的最大权值和。

为了方便计算,按照所有点按照深度排序,这样就用\(bfs\)便利子树就行了。

开始考虑前面的所有子树与当前子树的贡献

用一个指针从大到小维护所有可以的前面子树中的链

同时用单调队列维护一下单调性

每次取出满足经过的边数在\([L,U]\)之间,并且权值和最大的边出来进行组合,计算一下是否满足二分的答案就好了。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<set>
  8. #include<map>
  9. #include<vector>
  10. #include<queue>
  11. using namespace std;
  12. #define ll long long
  13. #define RG register
  14. #define MAX 111111
  15. inline int read()
  16. {
  17. RG int x=0,t=1;RG char ch=getchar();
  18. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  19. if(ch=='-')t=-1,ch=getchar();
  20. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  21. return x*t;
  22. }
  23. int n,L,U;
  24. double ans;
  25. struct Line{int v,next,w;}e[MAX<<1];
  26. int h[MAX],cnt=1;
  27. inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
  28. int size[MAX],Size,root,mx,MD;
  29. bool vis[MAX];
  30. double t[MAX],dis[MAX];
  31. void Getroot(int u,int ff)
  32. {
  33. size[u]=1;int ret=1;
  34. for(int i=h[u];i;i=e[i].next)
  35. {
  36. int v=e[i].v;if(vis[v]||v==ff)continue;
  37. Getroot(v,u);size[u]+=size[v];
  38. ret=max(ret,size[v]);
  39. }
  40. ret=max(ret,Size-size[u]);
  41. if(mx>ret)mx=ret,root=u;
  42. }
  43. int Q[MAX],H,T,Vis[MAX],dep[MAX];
  44. void bfs(int u,double d)
  45. {
  46. Q[H=T=1]=u;Vis[u]=true;
  47. while(H<=T)
  48. {
  49. int u=Q[H++];
  50. for(int i=h[u];i;i=e[i].next)
  51. {
  52. int v=e[i].v;if(vis[v]||Vis[v])continue;
  53. dep[v]=dep[u]+1;dis[v]=dis[u]+e[i].w-d;
  54. Q[++T]=v;Vis[v]=true;
  55. }
  56. }
  57. }
  58. int q[MAX];
  59. bool check(int u,double d)
  60. {
  61. bool fl=false;int md=0;
  62. for(int ee=h[u];ee&&!fl;ee=e[ee].next)
  63. {
  64. int v=e[ee].v;if(vis[v])continue;
  65. dis[v]=e[ee].w-d;dep[v]=1;
  66. bfs(v,d);
  67. int hh=1,tt=0,j=md;
  68. for(int i=1;i<=T;++i)
  69. {
  70. while(j>=0&&j+dep[Q[i]]>=L)
  71. {
  72. while(hh<=tt&&t[q[tt]]<t[j])--tt;
  73. q[++tt]=j;--j;
  74. }
  75. while(hh<=tt&&dep[Q[i]]+q[hh]>U)++hh;
  76. if(hh<=tt&&dis[Q[i]]+t[q[hh]]>=0)fl=true;
  77. }
  78. md=max(md,dep[Q[T]]);
  79. for(int i=1;i<=T;++i)
  80. {
  81. Vis[Q[i]]=false;
  82. t[dep[Q[i]]]=max(t[dep[Q[i]]],dis[Q[i]]);
  83. }
  84. }
  85. for(int i=1;i<=md;++i)t[i]=-1e12;
  86. return fl;
  87. }
  88. void Calc(int u)
  89. {
  90. double l=ans,r=MD;
  91. while(r-l>1e-4)
  92. {
  93. double mid=(l+r)/2;
  94. if(check(u,mid))l=mid;
  95. else r=mid;
  96. }
  97. ans=l;
  98. }
  99. void DFS(int u)
  100. {
  101. vis[u]=true;Calc(u);
  102. for(int i=h[u];i;i=e[i].next)
  103. {
  104. int v=e[i].v;if(vis[v])continue;
  105. Size=size[v];mx=n;Getroot(v,0);
  106. DFS(root);
  107. }
  108. }
  109. int main()
  110. {
  111. n=read();L=read();U=read();
  112. for(int i=1;i<n;++i)
  113. {
  114. int u=read(),v=read(),w=read();
  115. Add(u,v,w);Add(v,u,w);MD=max(MD,w);
  116. }
  117. Size=mx=n;Getroot(1,0);
  118. DFS(root);
  119. printf("%.3lf\n",ans);
  120. return 0;
  121. }

【BZOJ1758】【WC2010】重建计划(点分治,单调队列)的更多相关文章

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

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

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

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

  3. BZOJ1758: [Wc2010]重建计划

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Wince 中访问WCF服务

    由于本文并非WinCE开发普及篇,所以一些WinCE开发和WCF开发的基础还请移步百度和谷歌寻找答案,然后结合本文开发出WinCE中如何访问WCF,谢谢. 开发环境 IDE:Visual Studio ...

  2. JS继承方法

    1.原型链: 每个构造函数都有一个原型对象,且有一个指针指向该原型对象(prototype),原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个指向原型对象的内部指针(p ...

  3. Lua学习笔记(6): 函数

    Lua的函数 函数用于简化程序,当某些工作需要重复执行的时候就可以使用函数减轻工作量(虽然复制粘贴也行) 语法: function 函数名(参数列表) 函数体 return 返回值 end --结束标 ...

  4. File Transfer(并查集)

    题目大意:将多个电脑通过网线连接起来,不断查询2台电脑之间是否连通. 问题来源:中国大学mooc 05-树8 File Transfer (25 分) We have a network of com ...

  5. Dsniff简介

    原文发表于:2010-09-25 转载至cu于:2012-07-21 前两天因为看局域网安全的视频中介绍dsniff,也想自己安装下来看看效果.简单的使用没什么难的(高级使用就需要研究文档了),但是安 ...

  6. AI智能外呼机器人网络拓扑结构笔记

    最近开发了一套AI智能外呼机器人系统,系统主要有3部分组成:web管理平台:呼叫机器人:SIP软交换.具体网络拓扑结构如下图: 三部分主要功能如下: 1.web管理平台:话术管理.任务管理.线路管理. ...

  7. R之RMySQL

    linux,mysql和R的版本信息: Linux naci 3.19.0-16-generic #16-Ubuntu SMP Server version: 5.6.24-0ubuntu2 (Ubu ...

  8. uc浏览器的用户体验

    用户界面: 我认为,uc浏览器的用户界面还是很招人喜欢的,可以很容易让用户找到自己想看的网页.简单快捷. 记住用户的选择: uc在每次用户访问完网站之后都会记住用户访问的高频网站,以便下次用户可以更好 ...

  9. Pyhont:内建函数enumerate

    1.enumerate的中文意思 2.enumerate参数为可遍历的变量,如字符串.列表等,其返回值为enumerate类. 3.enumerate多用在for循环中得到计数 . [注]:若在for ...

  10. shader language学习(1)——shader language简介背景

    shader language,称为着色语言,shade在英语是阴影.颜色深浅的意思.shader language基于物体本身属性和光照条件,计算美格橡塑的颜色值. 实际上这种解释具有明显的时代局限 ...