传送门

Description

Solution

时隔多年,补上了这题的长链剖分写法

感觉比点分治要好写的多

我们假设\(pos\)是当前点的\(dfn\),它距离所在链的底端的边的数量是\(len\),距离是\(siz\)

那么我们要求得\(g[pos...pos+len]\)

其中\(g[pos+i]+siz\)表示的是当前点往下长度为\(i\)的最长链的大小

初始情况下,\(g[pos]=-siz[pos]\)

为什么要这么写呢?

因为转移重儿子的时候,我们直接把数组右移了一位,这样子定义使得原先的值仍然有意义

考虑如何转移?

对于一个轻儿子,\(dfn\)为\(pv\)

那么\(当前点,轻儿子g[pos+j+1]\leftarrow siz[pv]+g[pv+j]+w(当前点,轻儿子)-siz\)

考虑如何更新答案

对于\(lca\)为当前点的链

  1. 首先计算一个端点就是当前点的:\((g[pos+i])_{min}+siz\)

  2. 然后是两个端点分别处于不同子树的

    枚举一个轻儿子子树内的链长:\(当前点,轻儿子(g[pos+i])_{min}+siz+(siz[pv]+g[pv+j])+(w(当前点,轻儿子))\)

求min的部分用线段树优化

Code 

#include<bits/stdc++.h>
#define ll long long
#define reg register
#define ri reg int i
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=1e5+5;
const double eps=1e-4,inf=0x3f3f3f3f;
double siz[MN],g[MN],ans,mid;
struct edge{int to,w,nex;}e[MN<<1];int hr[MN],en;
inline void ins(int x,int y,int w)
{
e[++en]=(edge){y,w,hr[x]};hr[x]=en;
e[++en]=(edge){x,w,hr[y]};hr[y]=en;
}
int dfn[MN],len[MN],mx[MN],w[MN],ind,n,L,R;
struct SegmentTree
{
#define ls (x<<1)
#define rs (x<<1|1)
#define Mid ((l+r)>>1)
double t[MN<<2];
inline void clear(){for(ri=0;i<(MN<<2);++i)t[i]=-inf;}
void Modify(int x,int l,int r,int a,double val)
{
if(l==r) return(void)(t[x]=max(t[x],val));
if(a<=Mid) Modify(ls,l,Mid,a,val);
else Modify(rs,Mid+1,r,a,val);
t[x]=max(t[ls],t[rs]);
}
double Query(int x,int l,int r,int a,int b)
{
if(l==a&&r==b) return t[x];if(a>b)return -inf;
if(b<=Mid) return Query(ls,l,Mid,a,b);
if(a>Mid) return Query(rs,Mid+1,r,a,b);
return max(Query(ls,l,Mid,a,Mid),Query(rs,Mid+1,r,Mid+1,b));
}
}T;
void dfs(int x,int f=0)
{
for(ri=hr[x];i;i=e[i].nex)if(e[i].to^f)
{
dfs(e[i].to,x);
if(len[e[i].to]>=len[mx[x]]) mx[x]=e[i].to,w[x]=e[i].w;
if(len[e[i].to]+1>len[x]) len[x]=len[e[i].to]+1;
}
}
void solve(int x,int f=0)
{
if(!dfn[x]) dfn[x]=++ind;
reg int i,j,pos=dfn[x];
if(mx[x]) solve(mx[x],x),siz[pos]=siz[pos+1]+w[x]-mid;
T.Modify(1,1,n,pos,g[pos]=-siz[pos]);
if(L<=len[x])
{
double tmp=T.Query(1,1,n,pos+L,pos+min(len[x],R));
ans=max(ans,tmp+siz[pos]);
}
for(i=hr[x];i;i=e[i].nex)if(e[i].to!=f&&e[i].to!=mx[x])
{
solve(e[i].to,x);reg int pv=dfn[e[i].to];
for(j=0;j<=len[e[i].to];++j)
{
double tmp=T.Query(1,1,n,pos+max(0,L-j-1),pos+min(len[x],R-j-1));
ans=max(ans,tmp+siz[pv]+siz[pos]+g[pv+j]+e[i].w-mid);
}
for(j=0;j<=len[e[i].to];++j)
{
double tmp=siz[pv]+g[pv+j]+e[i].w-mid-siz[pos];
if(tmp>g[pos+j+1]) T.Modify(1,1,n,pos+j+1,g[pos+j+1]=tmp);
}
}
}
bool check(){T.clear();ans=-inf;solve(1);return ans>=eps;}
int main()
{
n=read();L=read();R=read();
reg int i,x,y;
for(i=1;i<n;++i) x=read(),y=read(),ins(x,y,read());
dfs(1);double l=0.,r=1e6;
for(i=1;i<=40;++i)
{
if(l+eps>=r) break;
mid=(l+r)/2.;
if(check()) l=mid;else r=mid;
}
printf("%.3lf",l);
return 0;
}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

[WC2010]重建计划(长链剖分版)的更多相关文章

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

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

  2. 「WC2010」重建计划(长链剖分/点分治)

    「WC2010」重建计划(长链剖分/点分治) 题目描述 有一棵大小为 \(n\) 的树,给定 \(L, R\) ,要求找到一条长度在 \([L, R]\) 的路径,并且路径上边权的平均值最大 \(1 ...

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

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

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

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

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

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

  6. WC2010 BZOJ1758 重建计划_长链剖分

    题目大意: 求长度$\in [L,U]$的路径的最大边权和平均值. 题解 首先二分就不用说了,分数规划大家都懂. 这题有非常显然的点分治做法,但还是借着这个题学一波长链剖分. 其长链剖分本身也没啥,就 ...

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

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

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

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

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

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

随机推荐

  1. iOS - 小功能 跳转到淘宝或天猫的商品展示详情页

    最近做iOS项目的时候遇到一个需求,点击广告页,跳转到淘宝或天猫的商品详情页. 具体需要是这样: 1)安装了淘宝:跳转到淘宝详情页. 2)没装淘宝,装了天猫:跳转到天猫详情页 3)淘宝.天猫都没装:跳 ...

  2. centOS学习part6:安装oracle 11g

    0 大家好.上一章(http://www.cnblogs.com/souvenir/p/3881484.html)我们对oracle在centOS下的安装进行了各项环境准备,本章我们将正式进行oral ...

  3. asp.net代码审计起始篇之系统搭建

    最近开始学习asp.net的代码审计,在开始审计之前除了要对语言有些基本的了解,还需要会在本地搭建demo网站方便调试和复现漏洞 准备工作:操作系统:我用的是win10 数据库:我用的sql serv ...

  4. Linux (x86) Exploit 开发系列教程之三(Off-By-One 漏洞 (基于栈))

    off by one(栈)? 将源字符串复制到目标缓冲区可能会导致off by one 1.源字符串长度等于目标缓冲区长度. 当源字符串长度等于目标缓冲区长度时,单个NULL字节将被复制到目标缓冲区上 ...

  5. Android 低功耗蓝牙BLE 开发注意事项

    基本概念和问题 1.蓝牙设计范式? 当手机通过扫描低功耗蓝牙设备并连接上后,手机与蓝牙设备构成了客户端-服务端架构.手机通过连接蓝牙设备,可以读取蓝牙设备上的信息.手机就是客户端,蓝牙设备是服务端. ...

  6. mtd交叉编译mkfs命令

    下载 mtd:ftp://ftp.infradead.org/pub/mtd-utils/ zlib:http://www.zlib.net/ lzo:http://bouchez.info/lzo. ...

  7. Spring事务传播机制与隔离机制

    详情查看 https://www.jianshu.com/p/249f2cd42692

  8. 邮件学习过程中关于request.POST的使用

    今天的话主要的精力都集中在邮件系统demo的实现,因为自己个人技术有限,所以做出来的相当简陋,在其中碰到的问题其实也是比较多的,对于基于django的邮件相对来说比较容易,然后就是在提交数据,获取po ...

  9. 大数据技术之Hadoop3.1.2版本HA模式

    大数据技术之Hadoop3.1.2版本HA模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Hadoop的HA特点 1>.主备NameNode 2>.解决单点故障 ...

  10. 配置数据源和配置jpa的yml文件

    spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root url: j ...