[WC2010]重建计划 长链剖分
[WC2010]重建计划
又一道长链剖分好题。
这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分。
如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结。
首先一看求平均值最大,马上想到套个二分,每次把边权变为原来的边权减去二分的答案,看树上有没有长度在\(L\)和\(U\)之间的正权链就好了。
于是乎问题就转变成了求树上权值和最大的链,这时马上想到我们以前做过的一道题P2993 [FJOI2014]最短路径树问题 题解,我已经在这道题的题解中把需要的思想讲明白了,如果你还不会那道题,最好先去做一做。对于这道题,就是开一个标记数组\(b\)记录增量,注意到我们可选的链长是一段区间,考虑用线段树来维护区间最大值。对于每一时刻,线段树上维护的信息都是实际信息减去当前长链顶端的标记值,这样处理元素间的相对大小关系没有改变,于是可以维护区间最大值,且保证了单次转移\(O(logn)\)的复杂度,总的复杂度是\(O(n(logn)^2)\),和点分治一样。
下面的代码没有采用一贯的指针写法,而是用了长链剖分之后的dfs序来记录答案(方便在线段树上统计),事实上二者是等价的。
#include<cstdio>
#include<cctype>
#include<algorithm>
#define R register
#define I inline
#define D double
using namespace std;
const int S=100003,N=200003,M=400003,inf=1e6;
const D eps=1e-5;
char buf[S],*p1,*p2;
I char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,S,stdin),p1==p2)?EOF:*p1++;}
I int rd(){
R int f=0; R char c=gc();
while(c<48||c>57) c=gc();
while(c>47&&c<58) f=f*10+(c^48),c=gc();
return f;
}
int h[S],s[N],g[N],w[N],d[S],t[S],p[S],q[S],f[S],u[S],c,e,G,n,L,U;
D a[S],b[S],o[M],m;
I void add(int x,int y,int z){s[++c]=h[x],h[x]=c,g[c]=y,w[c]=z;}
void bld(int k,int l,int r){o[k]=-inf;
if(l==r) return ;
R int p=k<<1,q=p|1,m=l+r>>1;
bld(p,l,m),bld(q,m+1,r);
}
void mdf(int k,int l,int r,int x,D v){
if(l==r){o[k]=max(o[k],v); return ;}
R int p=k<<1,q=p|1,m=l+r>>1;
if(x<=m) mdf(p,l,m,x,v);
else mdf(q,m+1,r,x,v);
o[k]=max(o[p],o[q]);
}
D qry(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return o[k];
R int p=k<<1,q=p|1,m=l+r>>1; D v=-inf;
if(x<=m) v=max(v,qry(p,l,m,x,y));
if(m<y) v=max(v,qry(q,m+1,r,x,y));
return v;
}
void dfs1(int x,int f){p[x]=f,t[x]=d[x]=d[f]+1;
for(R int i=h[x],y;i;i=s[i])
if((y=g[i])^f){dfs1(y,x);
if(t[y]>t[x]) t[x]=t[y],q[x]=y,u[x]=w[i];
}
}
void dfs2(int x){if(!f[x]) f[x]=++e;
R int i,j,y,l=f[x],r,v,k=t[x]-d[x]; D o=-inf; a[l]=b[l]=0;
if(q[x]) dfs2(q[x]),b[l]=b[l+1]+u[x]-m,a[l]=-b[l];
for(mdf(1,1,n,l,a[l]),i=h[x];i;i=s[i])
if((y=g[i])^p[x]&&y^q[x]){dfs2(y),r=f[y];
for(j=1,v=t[y]-d[y]+1;j<=v;++j)
if(L-j<=k) o=max(o,a[r+j-1]+b[l]+b[r]+w[i]-m+qry(1,1,n,l+max(1,L-j),l+min(U-j,k)));
for(j=1;j<=v;++j)
if(a[r+j-1]+b[r]-b[l]+w[i]-m>a[l+j])
a[l+j]=a[r+j-1]+b[r]-b[l]+w[i]-m,mdf(1,1,n,l+j,a[l+j]);
}
if(k>=L) o=max(o,b[l]+qry(1,1,n,l+L,l+min(U,k)));
if(o>=0) G=1;
}
I void chk(){G=0,bld(1,1,n),dfs2(1);}
int main(){
R int i,x,y,z; D l=0,r=inf;
for(n=rd(),L=rd(),U=rd(),i=1;i<n;++i)
x=rd(),y=rd(),z=rd(),add(x,y,z),add(y,x,z);
for(dfs1(1,0);r-l>eps;G?l=m:r=m) m=(l+r)*0.5,chk();
printf("%.3lf",l);
return 0;
}
常数被点分暴踩了
[WC2010]重建计划 长链剖分的更多相关文章
- 「WC2010」重建计划(长链剖分/点分治)
「WC2010」重建计划(长链剖分/点分治) 题目描述 有一棵大小为 \(n\) 的树,给定 \(L, R\) ,要求找到一条长度在 \([L, R]\) 的路径,并且路径上边权的平均值最大 \(1 ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...
- 2019.01.21 bzoj1758: [Wc2010]重建计划(01分数规划+长链剖分+线段树)
传送门 长链剖分好题. 题意简述:给一棵树,问边数在[L,R][L,R][L,R]之间的路径权值和与边数之比的最大值. 思路: 用脚指头想都知道要01分数规划. 考虑怎么checkcheckcheck ...
- WC2010 BZOJ1758 重建计划_长链剖分
题目大意: 求长度$\in [L,U]$的路径的最大边权和平均值. 题解 首先二分就不用说了,分数规划大家都懂. 这题有非常显然的点分治做法,但还是借着这个题学一波长链剖分. 其长链剖分本身也没啥,就 ...
- [WC2010]重建计划(长链剖分版)
传送门 Description Solution 时隔多年,补上了这题的长链剖分写法 感觉比点分治要好写的多 我们假设\(pos\)是当前点的\(dfn\),它距离所在链的底端的边的数量是\(len\ ...
- BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)
题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...
- [WC2010]重建计划(长链剖分+线段树+分数规划)
看到平均值一眼分数规划,二分答案mid,边权变为w[i]-mid,看是否有长度在[L,R]的正权路径.设f[i][j]表示以i为根向下j步最长路径,用长链剖分可以优化到O(1),查询答案线段树即可,复 ...
- 洛谷 P4292 - [WC2010]重建计划(长链剖分+线段树)
题面传送门 我!竟!然!独!立!A!C!了!这!道!题!incredible! 首先看到这类最大化某个分式的题目,可以套路地想到分数规划,考虑二分答案 \(mid\) 并检验是否存在合法的 \(S\) ...
随机推荐
- C/C++中作用域详解
转自:http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777433.html 作用域规则告诉我们一个变量的有效范围,它在哪儿创建,在哪儿 ...
- Appfuse搭建过程(下源代码不须要maven,lib直接就在项目里(否则痛苦死!))
什么是Appfuse:AppFuse是一个集成了众多当前最流行开源框架与工具(包含Hibernate.ibatis.Struts.Spring.DBUnit.Maven.Log4J.Struts Me ...
- 【[SCOI2010]序列操作】
好颓啊,我竟然来写了一道恶心的板子 旁边的魏佬嘲讽我,还用欺负我 嘤嘤嘤 那就不膜魏佬了 嘤嘤嘤 这是一道无聊的板子 看到这些操作,我们看到这些操作就知道我们需要维护的东西了 首先那个最长的连续的\( ...
- Kali-linux使用社会工程学工具包(SET)
社会工程学工具包(SET)是一个开源的.Python驱动的社会工程学渗透测试工具.这套工具包由David Kenned设计,而且已经成为业界部署实施社会工程学攻击的标准.SET利用人们的好奇心.信任. ...
- linux各种压缩包的压缩和解压方法
.tar/.war(tar是打包,不是压缩) 解包:tar xvf FileName.tar / FileName.war 打包:tar cvf FileName.tar DirName .gz 解压 ...
- Springboot中使用ibatis输出日志
logging.level.org.apache.ibatis=DEBUG logging.level.org.mybatis=DEBUG logging.level.java.sql.Connect ...
- Selenium自动化测试之结果处理
Selenium自动化测试之结果处理 一.断言 断言相当于性能测试中的检查点,常用断言种类很多,具体可以查看断言API:判断预期结果和实际结果是否一致,断言成功,程序继续处理,失败则终止运行,示例如下 ...
- nginx编译问题:make[1]: *** [/usr/local/pcre//Makefile] Error 127
解决方法: 是由于nginx高版本的需要使用pcre原文件路径. 解压pcre-7.9.tar.gz 例如解压后位置在 /home/wang/pcre-7.9位置 使用nginx配置的时候 ./con ...
- Oracle ddl 和 dml 操作
ddl 操作 窗口设置用户权限的方法 Oracle的数据类型 按住Ctrl点击表名 ,可以鼠标操作 插入的数据需要满足创建表的检查 主表clazz删除数据从表设置级联也会一同删除 有约束也 ...
- java核心技术-多线程之线程内存模型
对于每一种编程语言,理解它的内存模型是理所当然的重要.下面我们从jvm的内存模型来体会下java(不限java语言,严格来讲是JVM内存模型,所有JVM体系的变成语言均适用)的内存模型. 堆: 就是我 ...