description

题面

给个树,第\(i\)个点有两个权值\(a_i\)和\(b_i\),现在求一条长度为\(m\)的路径,使得\(\frac{\sum a_i}{\sum b_i}\)最小

data range

\[m\le n\le 2\times 10^5
\]

solution

0/1分数规划?二分吧。

二分一个值\(S\),要使得\(\frac{\sum a_i}{\sum b_i}\le S\)

那么$$\sum(a_i-Sb_i)\le0$$

把每个点的点权做成这个,然后\(DP\ check\)最优答案是否\(\le 0\)就行

如何\(DP\)?

暴力的,\(f_{i,j}\)表示\(i\)子数内长度为\(j\)的链的最优解,转移是\(O(n^2)\)的

按照深度的树上\(DP\)可以使用长链剖分优化到\(O(n)\)

总复杂度就是\(O(nlog\sum w)\)

code

#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define FILE "cdcq_b"
#define mp make_pair
#define pb push_back
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-4;
const int mod=998244353;
const int N=200010;
const dd pi=acos(-1);
const int inf=2147483647;
const ll INF=1e18+1;
const ll P=100000;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
} il void file(){
srand(time(NULL)+rand());
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
} int n,m;dd x[N],y[N];
int head[N],nxt[N<<1],to[N<<1],cnt;
int len[N],son[N];
void dfs1(int u,int fa){
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa)continue;
dfs1(v,u);if(len[son[u]]<len[v])son[u]=v;
}
len[u]=len[son[u]]+1;
} dd *pos,f[N],*A[N],tag[N],ans,K;
void dfs2(int u,int fa){
pos++;A[u]=pos;dd *a=A[u];
if(!son[u]){
a[0]=x[u]*1.0-K*y[u];
if(m==1)ans=min(ans,a[0]);
return;
}
dfs2(son[u],u); tag[u]=tag[son[u]]+x[u]*1.0-K*y[u];
a[0]=x[u]*1.0-K*y[u]-tag[u];
dd *b;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa||v==son[u])continue;
dfs2(v,u);b=A[v];
if(m==1)ans=min(ans,b[0]+tag[v]);
else
for(RG int j=0;j<m-1&&j<len[v];j++)
if(m-j-2<len[u])ans=min(ans,b[j]+tag[v]+a[m-j-2]+tag[u]);
for(RG int j=0;j<len[v];j++)
a[j+1]=min(a[j+1],b[j]+tag[v]+x[u]*1.0-K*y[u]-tag[u]);
}
if(len[u]>=m)ans=min(ans,a[m-1]+tag[u]);
} dd g[N];
void dfs3(int u,int fa){
if(!son[u]){g[u]=x[u]*1.0-K*y[u];ans=min(ans,g[u]);return;}
dfs3(son[u],u);if(g[son[u]]<0)g[u]+=g[son[u]];else g[u]=0;
for(RG int i=head[u];i;i=nxt[i]){
RG int v=to[i];if(v==fa||v==son[u])continue;
dfs3(v,u);ans=min(ans,g[u]+x[u]*1.0-K*y[u]+g[v]);
g[u]=min(g[u],g[v]);
}
g[u]+=x[u]*1.0-K*y[u];ans=min(ans,g[u]);
} il bool check(){
ans=INF;
if(m!=-1){pos=f;memset(f,0,sizeof(f));dfs2(1,0);}
else dfs3(1,0);
return ans<eps;
} int main()
{
file();
RG dd l=0,r=0,mid,as=-INF;
scanf("%d%d",&n,&m);
if(n==1||(m!=-1&&m>=n)){puts("-1");return 0;}
for(RG int i=1;i<=n;i++){scanf("%lf",&x[i]);r+=x[i];}
for(RG int i=1;i<=n;i++){
scanf("%lf",&y[i]);
}
for(RG int i=1,u,v;i<n;i++){
u=read();v=read();
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;
}
dfs1(1,0); while(r-l>=eps){
K=mid=(l+r)/2;
if(!check())l=mid;
else as=mid,r=mid;
} if(as==-INF)puts("-1");
else printf("%.2lf\n",as);
return 0;
}

[COGS2652]秘术「天文密葬法」的更多相关文章

  1. 【COGS2652】秘术「天文密葬法」(长链剖分,分数规划)

    [COGS2652]秘术「天文密葬法」(长链剖分,分数规划) 题面 Cogs 上面废话真多,建议直接拉到最下面看一句话题意吧: 给个树,第i个点有两个权值ai和bi,现在求一条长度为m的路径,使得Σa ...

  2. cogs 2652. 秘术「天文密葬法」(0/1分数规划 长链剖分 二分答案 dp

    http://cogs.pro:8080/cogs/problem/problem.php?pid=vSXNiVegV 题意:给个树,第i个点有两个权值ai和bi,现在求一条长度为m的路径,使得Σai ...

  3. 2019.03.11 COGS2652 秘术(天文密葬法)(分数规划+长链剖分)

    传送门 题意:nnn个点的树,每个点两个值a,ba,ba,b,问长度为mmm的路径∑ai∑bi\frac{\sum a_i}{\sum b_i}∑bi​∑ai​​的最大值. 思路:一眼要01分数规划, ...

  4. 对于前端,「微信小程序」其实不美好

    微信小程序开放公测了,9月底我曾经写过一篇 「微信小程序」来了,其中最后一句:"谢天谢地,我居然还是个前端". 这种火爆的新事物总是令人激动,感谢这个时代. 但是,当我真作为开发者 ...

  5. macOS安装「oh my zsh」

    目前常用的 Linux 系统和 OS X 系统的默认 Shell 都是 bash,但是真正强大的 Shell 是深藏不露的 zsh, 这货绝对是马车中的跑车,跑车中的飞行车,史称『终极 Shell』, ...

  6. 报名|「OneAPM x DaoCloud」技术公开课:Docker性能监控!

    如今,越来越多的公司开始 Docker 了,「三分之二的公司在尝试了 Docker 后最终使用了它」,也就是说 Docker 的转化率达到了 67%,同时转化时长也控制在 60 天内. 既然 Dock ...

  7. 企业运营对 DevOps 的「傲慢与偏见」

    摘要:出于各种原因,并非所有人都信任 DevOps .有些人觉得 DevOps 只不过给开发者改善产品提供了一个途径而已,还有的人觉得 DevOps 是一堆悦耳的空头支票,甚至有人认为 DevOps ...

  8. 「前端开发者」如何把握住「微信小程序」这波红利?

    由于前两周一直在老家处理重要事情,虽然朋友圈被「微信小程序」刷爆了,但并没有时间深入了解. 昨天回广州之后,第一件事情就是把「微信小程序」相关的文章.开发文档.设计规范全部看了一遍,基本上明白了「微信 ...

  9. 「花田对」CSDN程序员专场——谁来拯救技术宅!_豆瓣

    「花田对」CSDN程序员专场--谁来拯救技术宅!_豆瓣 「花田对」CSDN程序员专场--谁来拯救技术宅!

随机推荐

  1. 2 进程multiprocessing [mʌltɪ'prəʊsesɪŋ] time模块

    1.multiprocessing模块 multiprocessing模块就是跨平台版本的多进程模块. multiprocessing模块提供了一个Process类来代表一个进程对象, 2.Proce ...

  2. Django - day01 快速回忆ORM操作

    Django - day01 Model的增删改查找 得益于Django的ORM模型,用面向对象的思想来操作数据库使得数据库的操作一切变得简洁了很多. 0. 建表 在应用下的models.py中建立一 ...

  3. 微信小程序入门学习之事件 事件对象 冒泡非冒泡事件(1)

    这关于事件的学习,可以自己复制到微信开发者工具上自己运行试试. 首先这里有两个文件.js 和.wxml 文件 首先给出.js文件下代码 // pages/news/news.js Page({ /** ...

  4. Visual Stdio Code编辑Mark Down

    Visual Studio Code可以一边写Markdown一边预览了,而且不需要任何插件. 方法如下: 新建一个文件,以 .md 为后缀: Visual Studio Code 原生就支持高亮Ma ...

  5. solidity 智能合约操作

    合约编译 #!/usr/bin/env python # coding: utf8 import json import os # Solc Compiler from functools impor ...

  6. Python高级编程-多进程

    要让Python程序实现多进程(multiprocessing),我们先了解操作系统的相关知识. Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函数调用,调用一次,返回 ...

  7. 关于onclick和addeventlistener('click'),click的整理

    代码 $(function(){ $("#btn").click(function(){ console.log(2) }) $("#btn").click(f ...

  8. Python中的名字隐藏

    Python对于module文件中的name是没有private和public区分的,严格来说,在module文件重定义的任何name,都可以被外界访问.但是,对于 from module imort ...

  9. c#笔记整理 关于继承与多态等

    [ 塔 · 第 二 条 约 定 ] c#面向对象基础 整理private.protected.public.abstract等的异同 public 公有访问.不受任何限制. private 私有访问. ...

  10. apache 多端口访问 配置

    使用本地ip:端口号,或者修改hosts文件+域名的方法来进行本地多站点web调试.     注意这里是用apache 不是iis 1: 安装好AppServ2.5.9软件,官网是:[url]http ...