[COGS2652]秘术「天文密葬法」-长链剖分-01分数规划
来源:互联网 发布:excel 删除重复数据 编辑:程序博客网 时间:2024/05/22 05:03
秘术「天文密葬法」
题目说明:
路径的长度是点数
所有整数都是正整数
已添加一句话题意
【题目描述】
永琳需要协助紫解决异变!
在某个满月的夜晚,幻想乡的结界出现了异常,虽然目前还没有找到原因,不过有一点可以肯定的是,这次异变一定和满月有关。间隙妖怪紫在试图修复结界时需要永琳帮她排除满月产生的干扰,为了保护辉夜公主,永琳必须协助紫解决这次异变,所以她打算再次使用符卡”秘术「天文密葬法」”来用虚假的月亮替换真实的满月,但是她在使用符卡的时候出现了一些问题。
“秘术「天文密葬法」”由n个使魔组成,每个使魔都有一个能值和一个波值,同时存在n-1条能量通道将这n个使魔连接起来,并且每个使魔都能通过能量通道和其它所有使魔相连。
完成天文密葬法的关键步骤是在这n个使魔中找到一条用能量通道连接起来的路径,将大部分能量集中于这条路径来展开法术,然而路径上的使魔在法术张开时会产生共振,产生一个干扰值,干扰值等于路径上所有使魔能值的和除以波值的和。
为了确保计划顺利进行,永琳需要选择一条长度为m且干扰值最小的路径,虽然作为月之头脑,但此时永琳需要集中精力展开法术,所以她向你求助。
永琳在知道一个干扰值后就能快速找到这个干扰值对应的路径,你只需要告诉她所有路径中干扰值最小的路径干扰值是多少
答案四舍五入到小数点后两位
一句话题意:
给个树,第i个点有两个权值ai和bi,现在求一条长度为m的路径,使得Σai/Σbi最小
【输入格式】
第一行一个整数n,m,意义如上
如果m为-1则表示对长度没有限制(但路径不能为空
第二行n个整数,第i个整数ai表示第i个使魔的能值
第三行n个整数,第i个整数bi表示第i个使魔的波值
接下来n-1行,每行两个整数l,r,表示有一条能量路径连接第l个使魔和第r个使魔
一行中的所有整数均用空格隔开
【输出格式】
如果不存在长度为m的链,请输出-1
否则一行一个浮点数,表示干扰值最小的路径干扰值是多少
【样例输入1】
3 2
2 3 3
6 6 6
1 2
2 3
【样例输出1】
0.42
【样例输入2】
9 3
9 4 4 1 6 5 1 9 5
8 3 3 1 5 4 1 8 4
1 2
2 3
3 4
3 5
1 6
6 7
7 8
6 9
【样例输出2】
1.15
【数据范围】
m<=n<=200000
ai,bi<=200000
《论根据名字选择题目的优越性》
看见名字直接被炸进来了……
思路:
ans=∑ai∑bi
可以很明显发现这是一个裸的01分数规划……
那么就变个形
∑ai−ans∗∑bi=0
然后就是惯用的二分答案了~
然后显然看到路径统计就会想到点分治……
然而点分治总复杂度为
不如考虑一种奇妙的方法——长链剖分。
长链剖分是树链剖分的一种,平时一般说树链剖分指的都是重链剖分。
长链剖分和重链剖分唯一的不同在于,长链剖分以子树中最深点的深度作为剖分的依据,而重链剖分则是以子树内点的个数为依据。
在重链剖分的情况下,如果进行一波dsu on tree,复杂度会是
然而当题目的询问关键字为点的深度时,可以改为使用长链剖分,复杂度为
为什么呢?因为咱每次用的都是每个儿子的长链进行更新,那么如果一条长链被算进了复杂度,那么就说明它不是它的父亲的长链,它的祖先就再也不会用到它了。
这样可以发现每个点被暴力统计的次数为
这题怎么用长链剖分呢?
刚才咱已经将问题转换为了判断树上长度为m的路径得到的上式的值的最小值为多少,用这个值去二分。
可考虑一个类似点分治的,很暴力的dp:
记
那么很显然需要使用每个儿子的
可以用同一点上,长度加起来为m的两个f值之和更新答案。
考虑到空间开不下,选择只开一维,预处理出dfs序,令
对于每个节点,秉承着不浪费每一丝空间的原则,每次咱取一段f上的位置以供当前节点使用。
如何确定这m个位置呢?
如果使用长链剖分,那么就是从其dfs序上的位置开始向后m个位置。
因为可以发现,在长链剖分下,重儿子的dfs序编号必然比当前节点大1。
那么重儿子分配到的会是从当前点的dfs序编号+1处开始,长度为m的一段数组。
而在朴素dp中,当前节点继承的儿子的每个f值恰好是其儿子的f值中所有下标整体+1,新增一个
也就是说,直接从当前点在dfs序上的位置开始取m个,并对这m个位置进行区间加,即可得到当前节点的f数组!
显然如果长度在f与最深相对深度取最小值的情况下,这是不会存在相交情况的。
那么这就做到了
那么这就做完了~
因为小小地卡了一波常数,可能代码看起来有点丑……
相应的成果是,短时间内上榜了~
估计也就是短时间内能上了……
#include<cstdio>#define getchar getchar_unlockedusing namespace std;typedef float db;const int N=2e5+9;const db eps=1e-3;int n,m;int to[N<<1],nxt[N<<1],beg[N],tot;int id[N],dep[N],siz[N],son[N],dfn;int a[N],b[N],dsiz[N],fl;db inc,tag[N],dp[N],ret;inline int read(){ int x=0;char ch=getchar(); while(ch<'0' || '9'<ch)ch=getchar(); while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar(); return x;}inline void chkmin(db &a,db b){if(a>b)a=b;}inline void add(int u,int v){ to[++tot]=v; nxt[tot]=beg[u]; beg[u]=tot; to[++tot]=u; nxt[tot]=beg[v]; beg[v]=tot;}void dfs1(int u,int fa){ siz[u]=dep[u]; son[u]=0; for(register int i=beg[u],v;i;i=nxt[i]) if((v=to[i])!=fa) { dep[v]=dep[u]+1; dfs1(v,u); if(siz[u]<siz[v]) siz[u]=siz[v],son[u]=v; } dsiz[u]=siz[u]-dep[u];}void dfs2(int u,int fa){ id[u]=++dfn; if(son[u]) { dfs2(son[u],u); for(register int i=beg[u],v;i;i=nxt[i]) if((v=to[i])!=fa && v!=son[u]) dfs2(v,u); }}void dfs(int u,int fa){ db cost=(db)a[u]-inc*(db)b[u]; db *f=&dp[id[u]],*ff; if(!son[u]) { f[0]=cost; tag[u]=0; if(!m) chkmin(ret,cost); return; } dfs(son[u],u); f[0]=-tag[son[u]]; tag[u]=tag[son[u]]+cost; for(register int i=beg[u],v;i;i=nxt[i]) if((v=to[i])!=fa && v!=son[u]) { dfs(v,u); ff=&dp[id[v]]; for(register int j=0;j<=dsiz[v] && j<m;j++) if(m-1-j<=dsiz[u]) chkmin(ret,f[m-1-j]+ff[j]+tag[u]+tag[v]); for(register int j=0;j<=dsiz[v];j++) chkmin(f[j+1],ff[j]+tag[v]-tag[u]+cost); } if(dsiz[u]>=m) chkmin(ret,f[m]+tag[u]);}inline bool judge(db x){ inc=x; ret=1e18; dfs(1,0); if(ret!=1e18)fl=1; return ret<=0;}int main(){ freopen("cdcq_b.in","r",stdin); freopen("cdcq_b.out","w",stdout); n=read();m=read()-1; for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) b[i]=read(); db l=1e18,r=1e2,mid; for(int i=1;i<=n;i++) chkmin(l,(db)a[i]/(db)b[i]); if(m==-2) { printf("%.2f\n",l); return 0; } for(int i=1;i<n;i++) add(read(),read()); dfs1(1,0); dfs2(1,0); if(!judge(r)) { puts("-1"); return 0; } while(r-l>eps) { mid=(l+r)/2.0; if(judge(mid)) r=mid; else l=mid; } printf("%.2f\n",l); return 0;}
- [COGS2652]秘术「天文密葬法」-长链剖分-01分数规划
- [Algorithm]01分数规划
- 01分数规划
- 总结01分数规划
- 01分数规划
- POJ3757 01分数规划
- 01分数规划
- 01分数规划问题
- 01分数规划
- 01分数规划
- 01分数规划
- <01分数规划>淬炼神体
- 01分数规划
- 01-分数规划专题
- [Algorithm]01分数规划
- 01分数规划
- 01分数规划
- 贪心+01分数规划
- BSS段、数据段、代码段、堆与栈
- 绘图和可视化(seaborn)
- 编程语言概览
- IE9下不打开F12调试工具无法打开页面的问题解决
- C语言的函数
- [COGS2652]秘术「天文密葬法」-长链剖分-01分数规划
- (Spring框架)单例和多例以及依赖注入
- concurrent-4-AQS-ReentrantLock-Lock
- JSON.stringify和JSON.parse
- C、C++之动态数组的实现二(C++版本)
- PHP获取汉字首字母并分组排序
- 从此折腾有了生命
- 第一行代码笔记 Activity
- ubuntu16.04和windows10双系统下,ubuntu根目录扩容方法