两题都是树分治。

  1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调整二分上界。假设一棵树树根为x,要求就是经过树根x的最大答案,不经过树根x的可以递归求解。假设B[i]为当前做到的一颗x的子树中的点到x的距离为i的最大权值,A[i]为之前已经做过的所有子数中的点到x的距离为i的最大权值(这里的权值是Σv(e)-i*avgvalue),那么对于当前子树的一个距离i,可以从之前处理的子树中取到树根x距离为L-i到U-i权值中最大的那个,判断B[i]+max(A[L-i],A[U-i])是否大于等于0,这里max(A[L-i],A[U-i])可以用一个单调队列求,每处理完一颗子树用B数组更新A数组。

2599数据范围在讨论里,比较简单。

代码:

 //bzoj1758
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstring>
#include<vector>
#include<cmath>
#include<string>
#define N 500010
#define M 1010
using namespace std;
double ans,A[N],B[N],P;
int AS,BS;
int pre[N],p[N],tt[N],ww[N],dp,n,L,U,a,b,c,father[N],s[N],flag[N],tmproot,i,j,l,r,f[N];
double left,right,mid;
void link(int x,int y,int z)
{
dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;ww[dp]=z;
}
void getroot(int x,int fa,int sum)
{
int i,f=;
i=p[x];
father[x]=fa;
s[x]=;
while (i)
{
if ((tt[i]!=fa)&&(!flag[tt[i]]))
{
getroot(tt[i],x,sum);
s[x]=s[x]+s[tt[i]];
if (s[tt[i]]>sum/) f=;
}
i=pre[i];
}
if (sum-s[x]>sum/) f=;
if (f==) tmproot=x;
}
void dfs(int x,int fa,int deep,double value)
{
int i;
i=p[x];
B[deep]=max(B[deep],value-mid*double(deep));
BS=max(deep,BS);
while (i)
{
if ((tt[i]!=fa)&&(!flag[tt[i]]))
dfs(tt[i],x,deep+,value+ww[i]);
i=pre[i];
}
}
void work(int x,int sum)
{
int i,root,ti,ff;
getroot(x,,sum);
root=tmproot;
flag[root]=;
i=p[root];
while (i)
{
if (!flag[tt[i]])
{
if (father[root]!=tt[i])
work(tt[i],s[tt[i]]);
else
work(tt[i],sum-s[root]);
}
i=pre[i];
}
//----------------------------------
left=;right=;ti=;
while (ti<=)
{
ti++;
mid=(left+right)/;
ff=;
for (i=;i<=AS;i++)
A[i]=P;AS=;
i=p[root];
while (i)
{
if (!flag[tt[i]])
{
for (j=;j<=BS;j++)
B[j]=P;BS=;
dfs(tt[i],,,ww[i]);
r=;l=;
for (j=min(U-,AS);j>=L;j--)
{
r++;f[r]=j;
while ((l<r)&&(A[f[r]]>=A[f[r-]]))
{
f[r-]=f[r];
r--;
}
}
for (j=;j<=BS;j++)
{ if ((L<=j)&&(j<=U))
if (B[j]>=) ff=; while ((l<=r)&&(f[l]+j>U)) l++;
if (L-j>)
{
r++;f[r]=L-j;
while ((l<r)&&(A[f[r]]>=A[f[r-]]))
{
f[r-]=f[r];
r--;
}
if (A[f[l]]+B[j]>=) ff=;
}
}
for (j=;j<=BS;j++)
A[j]=max(A[j],B[j]);
AS=max(AS,BS);
}
if (ff) break;
i=pre[i];
} if (ff) left=mid;else right=mid;
}
ans=max(ans,left);
flag[root]=;
}
int main()
{
scanf("%d",&n);
scanf("%d%d",&L,&U);
P=;
P=-P*P;
for (i=;i<=n-;i++)
{
scanf("%d%d%d",&a,&b,&c);
link(a,b,c);
link(b,a,c);
}
for (i=;i<=n;i++)
{
A[i]=P;
B[i]=P;
}
ans=;
work(,n);
printf("%.3lf",ans);
}
 //bzoj2599
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstring>
#include<vector>
#include<cmath>
#include<string>
#define N 1000010
#define M 1010
#define P 1000000007
using namespace std;
int i,j,p[N],tt[N],s[N],father[N],ww[N],pre[N],tmproot,n,m;
int dp,flag[N],a,b,c,f[N],g[N],AS,BS,A[N],B[N],ans;
void link(int x,int y,int z)
{
dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;ww[dp]=z;
}
void getroot(int x,int fa,int sum)
{
int i,f=;
i=p[x];
father[x]=fa;
s[x]=;
while (i)
{
if ((tt[i]!=fa)&&(!flag[tt[i]]))
{
getroot(tt[i],x,sum);
s[x]=s[x]+s[tt[i]];
if (s[tt[i]]>sum/) f=;
}
i=pre[i];
}
if (sum-s[x]>sum/) f=;
if (f==) tmproot=x;
}
void dist(int x,int fa,int deep,int value)
{
int i;
i=p[x];
if (value<=m)
{
if (g[value]==0x37373737)
{
BS++;
B[BS]=value;
}
g[value]=min(g[value],deep);
}
else
return;
while (i)
{
if ((tt[i]!=fa)&&(!flag[tt[i]]))
dist(tt[i],x,deep+,value+ww[i]);
i=pre[i];
} }
void work(int x,int sum)
{
int i,root;
getroot(x,,sum);
root=tmproot;
flag[root]=;
i=p[root];
while (i)
{
if (!flag[tt[i]])
{
if (tt[i]==father[root])
work(tt[i],sum-s[root]);
else
work(tt[i],s[tt[i]]);
}
i=pre[i];
}
//-----------------------------
for (i=;i<=AS;i++)
f[A[i]]=0x37373737;AS=;
i=p[root];
while (i)
{
if (!flag[tt[i]])
{
for (j=;j<=BS;j++)
g[B[j]]=0x37373737;BS=;
dist(tt[i],,,ww[i]);
for (j=;j<=BS;j++)
ans=min(ans,g[B[j]]+f[m-B[j]]);
for (j=;j<=BS;j++)
if (f[B[j]]==0x37373737)
{
AS++;A[AS]=B[j];
}
for (j=;j<=BS;j++)
f[B[j]]=min(f[B[j]],g[B[j]]);
}
i=pre[i];
}
flag[root]=;
}
int main()
{
scanf("%d%d",&n,&m);
for (i=;i<=n-;i++)
{
scanf("%d%d%d",&a,&b,&c);
a++;b++;
link(a,b,c);
link(b,a,c);
}
for (i=;i<=m;i++)
{
f[i]=0x37373737;
g[i]=f[i];
}
ans=0x37373737;
work(,n);
if (ans!=0x37373737)
printf("%d",ans);
else
printf("-1");
}

bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race的更多相关文章

  1. BZOJ1758: [Wc2010]重建计划

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. [bzoj2599][IOI2011]Race——点分治

    Brief Description 给定一棵带权树,你需要找到一个点对,他们之间的距离为k,且路径中间的边的个数最少. Algorithm Analyse 我们考虑点分治. 对于子树,我们递归处理,所 ...

随机推荐

  1. PHP基础语法: echo,var_dump, 常用函数:随机数:拆分字符串:explode()、rand()、日期时间:time()、字符串转化为时间戳:strtotime()可变参数的函数:PHP里数组长度表示方法:count($attr[指数组]);字符串长度:strlen($a)

    PHP语言原理:先把代码显示在源代码中,再通过浏览器解析在网页上 a. 1.substr;  //用于输出字符串中,需要的某一部分 <?PHP $a="learn php"; ...

  2. HTML5的新事件

    HTML 元素可拥有事件属性,这些属性在浏览器中触发行为,比如当用户单击一个 HTML 元素时启动一段 JavaScript. HTML 元素可拥有事件属性,这些属性在浏览器中触发行为,比如当用户单击 ...

  3. jdk1.7的collections.sort(List list)排序问题

    1.7使用旧排序: System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); 1.7 ...

  4. Simplest way to serve static data from outside the application server in a Java web application

    tomcat service.xml <Context docBase="/path/to/images" path="/images" /> re ...

  5. [LeetCode] Simplify Path(可以不用看)

    Given an absolute path for a file (Unix-style), simplify it. For example, path = "/home/", ...

  6. CentOS7 + linux kernel 3.10.94 compile 简记

    Linux kernel 一直以其开源著称,可以自己编译选择合适的模块,针对特定的系统可以有不同的编译选项 来源 此次编译的内核版本为3.10.94,从官网www.kernel.org下载而来,自己虚 ...

  7. C# BeginInvoke

    在用C#编写串口助手时,希望创建线程更新UI,网上有人采用BeginInvoke方法, 这里记录一下使用方法. 参考链接: http://blog.csdn.net/zaijzhgh/article/ ...

  8. logback配置详解(二)

    <appender> <appender>: <appender>是<configuration>的子节点,是负责写日志的组件. <appende ...

  9. iOS:消除项目中警告

    引言: 在iOS开发过程中, 我们可能会碰到一些系统方法弃用, weak.循环引用.不能执行之类的警告. 有代码洁癖的孩子们很想消除他们, 今天就让我们来一次Fuck 警告!! 首先学会基本的语句: ...

  10. python中几个常用的算术函数

    1.lambda函数(匿名函数) lambda函数使用方式:lambda[参数1,参数2....]:表达式,列表 实例如下: lambda x : x * 2,[1,2,3,4] lambda 2.r ...