[luogu 4292][bzoj 1758][WC2010] 重建计划(点分治 + dp + 单调队列优化 + 启发式合并)

[WC2010]重建计划

  • problem
  • solution
  • code

problem

洛谷指路

solution

一看那个道路平均价值的式子:AvgValue=∑e∈Sv(e)∣S∣\text{AvgValue}=\frac{\sum_{e\in S}v(e)}{|S|}AvgValue=SeSv(e) 就是 0/1分数规划 的样子。

所以考虑二分最终的答案 midmidmid,考虑是否有一条路径的平均价值 ≥mid\ge midmid,但这个形式仍然跟具体路径的条数有关。

不妨将每条边的边权都减去 midmidmid,问题转化为 check\text{check}check 是否有一条长度在 [L,U][L,U][L,U] 内且边权和 ≥0\ge 00 的路径。

路径问题就套路的点分治,处理经过分治中心的路径情况。

一条过分治中心的路径是由两个不同子树内的路径拼接起来的。

所以单独依次考虑分治中心的每个子树。

首先得 dfs 一遍子树,求出子树内每个点的距离分治中心的路径权值,即 dis[i]

考虑现在枚举的子树和之前已经处理过的子树拼接出来的路径。

要求两个路径的长度之和在 [L,U][L,U][L,U] 的范围内,而且我们并不关心具体是哪两个点,只关心这两个点的深度。并且整个操作都是为了找一条 ≥0\ge 00 的路径。

所以直接枚举长度(深度),并且长度相同的点取路径权值更大的点。

f[i] :前面处理过的子树中点深度为 iii 的,到分治中心路径权值的最大值。

g[i] :当前枚举的子树中点深度为 iii 的,到分治中心路径权值的最大值。

那么每次处理下一个子树前,还要进行二者的合并,即 f[i]=max(f[i],g[i])

这个信息的维护通过 dfs 每个子树可以获得,即 g[dep[u]]=max(g[dep[u]],dis[u])

然后枚举两个深度求:max⁡L≤i+j≤U{f[i]+g[j]}\max_{L\le i+j\le U}\Big\{f[i]+g[j]\Big\}maxLi+jU{f[i]+g[j]}

转换一下当现在枚举的子树选择的深度 jjj 固定时,有 L−j≤i≤U−jL-j\le i\le U-jLjiUj

发现随着 jjj 的增大,iii 枚举的范围也在增大。

所以可以单调队列维护 iii 优化成线性。

如果只是这样,跑出来可能会发现 TLE

考虑这样一种情况:L=1,U=n2L=1,U=\frac n2L=1,U=2n,数据构造了一条点数为 n2\frac n22n 的链,然后在链的一端构造了一个点数为 n2\frac n22n 的菊花。

分治中心显然是会选在菊花和链的交界处。

然后如果第一棵子树选择访问了那一条链,更新了长度在 111n2\frac n22n 的最优答案。

再去访问菊花中的每一个点的时,则每一次都需要枚举 1∼n21\sim \frac n212n,对单调队列进行初始化,结果导致光这一层分治的复杂度就变成了 O(n2)O(\frac n2)O(2n)

事实上,这个问题源于每一次单调队列初始化的复杂度其实是 O(min(U−1,MaxLen))O\Big(min(U−1,MaxLen)\Big)O(min(U1,MaxLen)) 的,其中MaxLenMaxLenMaxLen 为之前访问的所有子树中路径的最长长度(最大深度)。

如果我们在本身 UUU 就比较大的情况下,选择先操作较长的子树,将 MaxLenMaxLenMaxLen 变到很大,然后再不断地进行后续单调队列的操作,那复杂度肯定就炸了。

解决方法就是启发式合并,按照子树的最长长度(最大深度)排序,从小到大处理子树。

sort(s+1,s+cnt+1,[](int x, int y){ return h[x] < h[y]; })

这样就有正确的时间复杂度 O(nlog⁡2n)O(n\log^2n)O(nlog2n)

code

#include <bits/stdc++.h>
using namespace std;
#define eps 1e-4
#define maxn 100005
#define inf 0x7f7f7f7f
double ans;
int n, L, U, N, Max, root, cnt = 1;
double f[maxn], g[maxn], dis[maxn];
int h[maxn], s[maxn], q[maxn], dep[maxn], len[maxn], siz[maxn], head[maxn];
bool vis[maxn];
struct node { int to, nxt, d; }E[maxn << 1];void dfs( int u, int fa ) {siz[u] = 1; int maxson = 0;for( int i = head[u];i;i = E[i].nxt ) {int v = E[i].to;if( vis[v] or v == fa ) continue;else dfs( v, u );siz[u] += siz[v];maxson = max( maxson, siz[v] );}maxson = max( maxson, N - siz[u] );if( maxson < Max ) Max = maxson, root = u;
}void dfs1( int u, int fa ) {dep[u] = dep[fa] + 1, h[u] = 1;for( int i = head[u];i;i = E[i].nxt ) {int v = E[i].to, w = E[i].d;if( vis[v] or v == fa ) continue;else len[v] = w, dfs1( v, u ), h[u] = max( h[u], h[v] + 1 );}
}void dfs2( int u, int fa, double mid ) {dis[u] = dis[fa] + len[u] - mid, g[dep[u]] = max( g[dep[u]], dis[u] );for( int i = head[u];i;i = E[i].nxt ) {int v = E[i].to;if( vis[v] or v == fa ) continue;else dfs2( v, u, mid );}
}bool check( double mid ) {double ret = -inf;for( int i = 1;i <= cnt;i ++ ) {for( int j = 1;j <= h[s[i]];j ++ ) g[j] = -inf;dfs2( s[i], root, mid );int head = 1, tail = 0;for( int j = 0;j <= h[s[i]];j ++ ) {while( head <= tail and q[head] > U - j ) head ++;if( L - j <= h[s[i]] ) {while( head <= tail and f[q[tail]] < f[L - j] ) tail --;q[++ tail] = L - j;}if( head <= tail ) ret = max( ret, f[q[head]] + g[j] );}for( int j = 1;j <= h[s[i]];j ++ ) f[j] = max( f[j], g[j] );}return ret > 0;
}void solve( int u ) {vis[u] = 1, dis[u] = 0, dep[0] = -1;dfs1( u, 0 );cnt = 0;for( int i = head[u];i;i = E[i].nxt )if( ! vis[E[i].to] ) s[++ cnt] = E[i].to;if( ! cnt ) return;sort( s + 1, s + cnt + 1, []( int x, int y ) { return h[x] < h[y]; });double l = ans, r = 1e6;while( r - l > eps ) {double mid = ( l + r ) / 2;for( int i = 1;i <= h[s[cnt]];i ++ ) f[i] = -inf; f[0] = 0;if( check( mid ) ) ans = max( ans, mid ), l = mid;else r = mid;}for( int i = head[u];i;i = E[i].nxt ) {int v = E[i].to;if( vis[v] ) continue;N = siz[v], Max = inf;dfs( v, u );solve( root );}
}int main() {scanf( "%d %d %d", &n, &L, &U );for( int i = 1, u, v, w;i < n;i ++ ) {scanf( "%d %d %d", &u, &v, &w );E[cnt] = { v, head[u], w }, head[u] = cnt ++;E[cnt] = { u, head[v], w }, head[v] = cnt ++;}Max = inf, N = n;dfs( 1, 0 );solve( root );printf( "%.3f\n", ans );return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316687.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cf1553C. Penalty

cf1553C. Penalty 题意&#xff1a; 有十轮点球&#xff0c;两个队伍轮流进行&#xff0c;1表示进&#xff0c;0表示不进&#xff0c;&#xff1f;表示未知&#xff0c;如果比赛没有了悬念将直接结束。现在让你预测一个情况&#xff0c;使得进行的轮数最少。裁判在决定停止点…

ASP.NET Core 基于JWT的认证(二)

上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍&#xff0c;这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用。.Net Core 2.2Visual Studio 2017ASP.NET Core WebAPI2在上一篇文章中&#xff0c;我们详细的介绍了JWT的知识&#xff0c;这…

P6774 [NOI2020] 时代的眼泪(分块)

前言 看到题目名&#xff1a;别骂了别骂了。 一道很中规中矩的YNOI吧。 卡在整块对整块的贡献上了。 这也确实算是本题最不好做的部分了。 前置知识&#xff1a;Yuno loves sqrt technology I 解析 区间逆序对加强版&#xff1f;很难不想到两道 YLST。 然而多了两维限制&a…

[NOIP2021] 数列(计数dp)

solution f[i][j][k][num][p]:2pf[i][j][k][num][p]:2^pf[i][j][k][num][p]:2p 选择了 iii 个&#xff0c;前 p−1p-1p−1 位 (202p−1)(2^0~2^{p-1})(20 2p−1) 已经选了jjj个&#xff0c;低位向高位进位上来 kkk&#xff0c;前 ppp 位已经确定有 numnumnum 个位置为 111&…

Xor sum HDU - 6955

Xor sum HDU - 6955 题意&#xff1a; 给定一个长度为n的整数序列&#xff0c;求其XOR和不小于k的最短连续子序列。 如果有多个相同长度的连续子序列&#xff0c;则打印具有最小左端点的连续子序列。 如果没有连续的子序列开关XOR总和不小于k&#xff0c;只需打印“-1”。 …

模板:子序列自动机(字符串)

所谓子序列自动机&#xff0c;就是根据子序列建立的自动机。 &#xff08;逃&#xff09; 前言 小清新算法。 解析 和其他自动机类似的&#xff0c;我们希望子序列自动机能且只能接受原串的所有子序列。 考虑一个问题&#xff1a;给你一个串 T&#xff0c;如何判断它是否是…

Docker最全教程之Go实战,墙裂推荐(十九)

前言与其他语言相比&#xff0c;Go非常值得推荐和学习&#xff0c;真香&#xff01;为什么&#xff1f;主要是可以直接编译成机器代码&#xff08;性能优越&#xff0c;体积非常小&#xff0c;可达10来M&#xff0c;见实践教程图片&#xff09;而且设计良好&#xff0c;上手门槛…

[BZOJ3093][Fdu校赛2012] A Famous Game(不等概率)

problem BOZJ3093 solution 逆概率公式&#xff0c;即贝叶斯(Bayes)公式&#xff1a; 假设 B1,B2,...,BnB_1,B_2,...,B_nB1​,B2​,...,Bn​ 是 Ω\OmegaΩ 的一个分割&#xff0c;P(A)>0P(A)>0P(A)>0&#xff0c;则有 P(Bk∣A)P(ABk)P(A)P(Bk)P(A∣Bk)∑i1nP(Bi)…

Mod, Or and Everything HDU - 6950

Mod, Or and Everything HDU - 6950 题意&#xff1a; 给你一个n,问(n%1) or (n%2) or … or (n %n)的值 题解&#xff1a; 无论n为奇偶&#xff0c;定义m(n-1)/2&#xff0c; 我们发现n mod i<m&#xff0c;而当i<m时&#xff0c;有n mod (n-i) i ,于是就有n mod i …

你注意到 .Net Framework 和 .Net Core 中使用 Session 的区别了吗?

在测试一个例子时发现的问题&#xff0c;这个示例实现的功能是刷新页面也能保持表格锁定列的状态&#xff0c;先看下页面的完成效果&#xff1a;测试中发现&#xff0c;几乎相同的代码&#xff1a;在 FineUIMvc&#xff08;Net Framework&#xff09;下没有问题&#xff1a;htt…

模板:拉格朗日乘子法(数学)

所谓拉格朗日乘子法&#xff0c;就是拉格朗日发明的乘子法。 &#xff08;逃&#xff09; 前言 曾经&#xff0c;我被它爆杀&#xff1b;如今&#xff0c;不同的日子&#xff0c;同样的题目&#xff0c;我却不再是曾经的我了。 因为我写模拟退火了。 也不能老是这么混着&…

[UOJ299][CTSC2017] 游戏

【CTSC2017】游戏 problem UOJ299 solution 定义 Xi:X_i:Xi​: 当前已知条件第 iii 局的状态 1/01/01/0&#xff08;胜/败&#xff09;。 将 XiCiX_iC_iXi​Ci​ 记为事件 AiA_iAi​。 假设现在已知条件共有 sss 个&#xff0c;即&#xff1a;第 k1∼sk_{1\sim s}k1∼s​…

Alice and Bob

Alice and Bob 题意&#xff1a; 两人博弈&#xff0c;每次一个人从一堆中拿k个&#xff0c;同时从另一堆拿k * s(s>0)个&#xff0c;问谁先不能拿 10000组数据,N<5000 题解&#xff1a; (x,y)表示第一堆石头数量为x&#xff0c;第二堆为y 如果(x,y)是必败状态&#…

一键发布部署vs插件[AntDeploy]开源了

deploy to remote server by one button click功能支持docker一键部署(支持netcore)支持iis一键部署(支持netcore和framework)(支持增量发布)(支持一键回滚)(支持点火)支持windows服务一键部署(支持netcore和framework)(支持增量发布)(支持一键回滚) 使用插件前我要发布一个net…

CF1257F Make Them Similar(meet in the middle,模拟退火)

前言 sto 退火大师_slb orz sto 正解大师_KHIN orz 只有我啥也不会&#xff0c;哈哈。 有趣的是&#xff0c;两种方法我都想到了一部分&#xff0c;然后都寄掉了。 这有趣个锤子。 解析 Sol1 考虑枚举最终的popcount&#xff0c;然后限制就变成了一个类似于高斯消元的形式…

Find 3-friendly Integers

Find 3-friendly Integers 题意&#xff1a; 定义一个自然数是精妙的&#xff0c;如果他存在一个字串(允许前导0)是3的倍数 问L到R中精妙的数的个数 题解&#xff1a; 数位dp可以做(但我不会。。。) 用结论来做&#xff0c;当n>100时(即为3位数时)必然是精妙的数&#x…

【学习笔记】平等博弈及常见的公平博弈类型

文章目录平等博弈nim堆SG定理nim和常见的公平博弈模型bash博弈nim博弈nim-k博弈wythoff博弈扩展wythoff博弈fibonacci博弈阶梯博弈green hackenbushMisre Nim博弈Every-SGnim积翻棋子游戏游戏的积&#xff0c;tartan定理平等博弈 G{L∣R},LRG\{L|R\},LRG{L∣R},LR&#xff0c;所…

Excel催化剂开源第31波-pdf相关功能实现及类库介绍

在Excel催化剂刚推出的pdf相关功能中&#xff0c;反馈很热烈&#xff0c;不止是用户层面好多人喜欢&#xff0c;也听到在.NET开发群里有询问pdf在winform上展现的功能诉求&#xff0c;一段时间没写开源篇&#xff0c;生怕大家以为Excel催化剂太小气了&#xff0c;不再开发了&am…

CF1526D Kill Anton(暴力)

前言 我的证明&#xff1a;这似乎非常对啊。 。。。 解析 直观感受&#xff1a;字母交错出现非常愚蠢。 然后就猜对了 为什么&#xff1f; 考虑两个相同但不相邻的字符 Ti,TjT_i,T_jTi​,Tj​&#xff0c;对应位置为 pi,pjp_i,p_jpi​,pj​。 夹在中间的字符 kkk 无非三种可…

Minimum spanning tree HDU - 6954

Minimum spanning tree HDU - 6954 题意&#xff1a; 给定n-1个点&#xff0c;编号从2到n&#xff0c;两点a和b之间的边权重为lcm&#xff08;a&#xff0c;b&#xff09;。请找出它们形成的最小生成树。 2<n<10000000 题解&#xff1a; 这题一看就眼熟。。。这不是去…