P4292-[WC2010]重建计划【长链剖分,线段树,0/1分数规划】
正题
题目链接:https://www.luogu.com.cn/problem/P4292
题目大意
给出\(n\)个点的一棵树,然后求长度在\([L,U]\)之间的一条路径的平均权值最大。
解题思路
先上二分\(0/1\)分数规划,然后变成求最长在\([L,U]\)之间的路径。
很经典的点分治问题,但是用线段树会\(T\),当然可以用单调队列但是我不会。
可以试下上长剖,线段树维护链上每个深度的最大值权值。然后枚举短的那条链的时候在长的那条上面线段树查询就好了。
时间复杂度\(O(n\log^2 n)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
const double inf=1e18,eps=1e-6;
struct node{
int to,next;
double w;
}a[N<<1];
int n,L,U,tot,cnt,ls[N];
int dep[N],len[N],son[N],rt[N];
double f[N],nw[N],ans;
struct SegTree{
double w[N<<5];int ls[N<<5],rs[N<<5];
void Change(int &x,int L,int R,int pos,double val){
if(!x)x=++cnt,ls[x]=rs[x]=0,w[x]=-inf;
if(L==R){w[x]=max(val,w[x]);return;}
int mid=(L+R)>>1;
if(pos<=mid)Change(ls[x],L,mid,pos,val);
else Change(rs[x],mid+1,R,pos,val);
w[x]=max(w[ls[x]],w[rs[x]]);return;
}
double Ask(int x,int L,int R,int l,int r){
if(l<L)l=L;if(r>R)r=R;
if(!x||l>r)return -inf;
if(L==l&&R==r)return w[x];
int mid=(L+R)>>1;
if(r<=mid)return Ask(ls[x],L,mid,l,r);
if(l>mid)return Ask(rs[x],mid+1,R,l,r);
return max(Ask(ls[x],L,mid,l,mid),Ask(rs[x],mid+1,R,mid+1,r));
}
}T;
void addl(int x,int y,double w){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;a[tot].w=w;
return;
}
void dfs(int x,int fa){
dep[x]=dep[fa]+1;
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(y==fa)continue;
dfs(y,x);
if(len[y]>len[son[x]])
son[x]=y,nw[x]=a[i].w;
}
len[x]=len[son[x]]+1;
return;
}
void solve(int x,int fa,int t,double k,double dis){
rt[x]=0;
if(son[x])solve(son[x],x,t,k,dis+nw[x]-k);
T.Change(rt[t],dep[t],dep[t]+len[t],dep[x],dis);
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(y==son[x]||y==fa)continue;
solve(y,x,y,k,dis+a[i].w-k);
for(int j=dep[y];j<=dep[y]+len[y];j++){
f[j]=T.Ask(rt[y],dep[y],dep[y]+len[y],j,j);
ans=max(ans,f[j]+T.Ask(rt[t],dep[t],dep[t]+len[t],2*dep[x]+L-j,2*dep[x]+U-j)-2*dis);
}
for(int j=dep[y];j<=dep[y]+len[y];j++)
T.Change(rt[t],dep[t],dep[t]+len[t],j,f[j]);
}
ans=max(ans,T.Ask(rt[t],dep[t],dep[t]+len[t],dep[x]+L,dep[x]+U)-dis);
return;
}
bool check(double k){
ans=T.w[0]=-inf;cnt=0;
solve(1,1,1,k,0);
return ans>-eps;
}
int main()
{
scanf("%d%d%d",&n,&L,&U);
for(int i=1;i<n;i++){
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
addl(x,y,w);addl(y,x,w);
}
len[0]=-1;dfs(1,1);
double l=0,r=1e6;
while(r-l>eps){
double mid=(l+r)/2.0;
if(check(mid))l=mid;
else r=mid;
}
check(1e6);
printf("%.3lf",(l+r)/2.0);
return 0;
}
P4292-[WC2010]重建计划【长链剖分,线段树,0/1分数规划】的更多相关文章
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- [WC2010]重建计划 长链剖分
[WC2010]重建计划 LG传送门 又一道长链剖分好题. 这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分. 如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结. 首先一看求平均值最大 ...
- [BZOJ2402]陶陶的难题II(树链剖分+线段树维护凸包+分数规划)
陶陶的难题II 时间限制:40s 空间限制:128MB 题目描述 输入格式 第一行包含一个正整数N,表示树中结点的个数. 第二行包含N个正实数,第i个数表示xi (1<=xi<= ...
- BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...
- 「WC2010」重建计划(长链剖分/点分治)
「WC2010」重建计划(长链剖分/点分治) 题目描述 有一棵大小为 \(n\) 的树,给定 \(L, R\) ,要求找到一条长度在 \([L, R]\) 的路径,并且路径上边权的平均值最大 \(1 ...
- 洛谷 P4292 - [WC2010]重建计划(长链剖分+线段树)
题面传送门 我!竟!然!独!立!A!C!了!这!道!题!incredible! 首先看到这类最大化某个分式的题目,可以套路地想到分数规划,考虑二分答案 \(mid\) 并检验是否存在合法的 \(S\) ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- 2019.01.21 bzoj1758: [Wc2010]重建计划(01分数规划+长链剖分+线段树)
传送门 长链剖分好题. 题意简述:给一棵树,问边数在[L,R][L,R][L,R]之间的路径权值和与边数之比的最大值. 思路: 用脚指头想都知道要01分数规划. 考虑怎么checkcheckcheck ...
- [WC2010]重建计划(长链剖分+线段树+分数规划)
看到平均值一眼分数规划,二分答案mid,边权变为w[i]-mid,看是否有长度在[L,R]的正权路径.设f[i][j]表示以i为根向下j步最长路径,用长链剖分可以优化到O(1),查询答案线段树即可,复 ...
随机推荐
- Windows莫名内存到百分之百,需要修改虚拟内存
借鉴别人的操作: https://blog.csdn.net/xjpdf10/article/details/82849112
- Specification使用in
//是否包含下级授权点 1 包含 2 不包含 List<AuthorizationPoint> authList = null; List<Long> pointIdList ...
- Gradient checking
所需文件:本地下载 Gradient Checking Welcome to the final assignment for this week! In this assignment you wi ...
- Sentinel限流、降级配置详解
安装Sentinel 下载sentinel-dashboard-1.8.2.jar 安装有jdk环境,8080端口未被占用 在jar包所在目录打开cmd,输入命令启动:java -jar sentin ...
- Redis-技术专区-帮从底层彻底吃透AOF技术原理
AOF持久化方式 AOF持久化方式是将redis的操作日志以追加的方式写入磁盘文件中.AOF持久化是以日志的形式记录服务器所处理的每一个写.删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看 ...
- Java动态代理底层实现
Java实现源码 上一节我们提到了Java动态代理的使用,接下来我们看一下他的具体实现. HelloInterface proxyHello = (HelloInterface) Proxy.newP ...
- Linux命令进阶篇之一
利用file命令查看那文件的类型 cd /etc 这里面的文件 命令:file 语法:file [-bLvz] 文件 解释:-b:显示结果,但是不显示文件名称 -L:直接显示符号链接所指向的文件的类型 ...
- IDEA使用教程+JRebel破解
下载与安装 https://www.jetbrains.com 不装任何插件 破解码 K03CHKJCFT-eyJsaWNlbnNlSWQiOiJLMDNDSEtKQ0ZUIiwibGljZW5zZW ...
- JS008. 跳转缓存滚动条高度并返回时过渡动画(window.pageYOffset & window.scrollTo & SessionStorage)
业务场景 从列表跳转详情页,通过操作返回列表页时,滚动条仍然处于跳转前的高度,并加上 ease-out 的过渡动画. 由于sessionStorage是随页面即关即消的,所以比起VUEX.localS ...
- Windows phone 8 触发器使用小结
引用空间: xmlns:ec="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expres ...