WC2010 重建计划

news/2024/11/6 16:48:41/文章来源:https://www.cnblogs.com/SFsaltyfish/p/18530538

谨以此纪念这个废物逝去的一天。

别看它是一道黑题但是它不配。

首先它长得很像分数规划,直接二分答案,这样就把每条边的边权看成了 \(V(e)-\text{mid}\),然后你希望求经过边数在 \([L,U]\) 之间的最长路径,判断它是否 \(\ge 0\)

考虑一个暴力 \(dp_{i,j}\) 表示 \(i\) 作为链顶,其子树长度为 \(j\) 的链最大的边权和是多少。

暴力转移是非常容易的:\(dp_{i,j}=\max_{(i,v,w)\in E}dp_{v,j-1}+w-\text{mid}\)

求解也是比较轻松的,考虑在转移 \(dp_{v,j-1}\to dp_{i,j}\) 之前,枚举 \(dp_{i,j},dp_{v,k}\) 在满足 \(j+k+1\in [L,U]\) 的情况下,\(\text{ans}=\max \{dp_{i,j}+dp_{v,k}\}\),本质上就是合并两颗子树的答案。

将求解稍微优化一下,由于二分,此时复杂度应该是 \(\mathcal{O}(n^2\log V)\)

考虑如何进一步的优化。观察到这个 \(dp\) 的定义和转移都非常符合我们长剖优化 DP 的形式。

直接套用我们在引例中使用长剖进行转移的形式,直接继承重儿子的 \(dp_{i,j}\),注意一下下标偏移即可,我们应该是可以非常容易的将 \(dp\) 的转移做到时空复杂度均为 \(\mathcal{O}(n)\) 的。

但是在转移完之后求解答案的过程却不那么好通过知道所有的 \(dp\) 值之后快速解决。

观察到在求解的 \(dp_{i,j}+dp_{v,k}\) 中,在知晓 \(j\) 的情况下,合法的 \(k\) 是连续的一段区间,故我们考虑直接将 \(dp\) 直接搬到线段树上去。

这样应该是比较好求解的,求解是在转移之前,通过查询区间最值,和长剖本身的复杂度,这一部分应该是 \(\mathcal{O}(n\log n)\)

但是新的问题出现了,线段树的下标偏移在继承重儿子的时候并不是直接左移那么简单的(疑似可以直接线段树合并,我不知道。)。故我们直接很暴力的,将 \(i\) 对应的在线段树上的 \(dp\) 值,储存在其在链顶处的线段树上所对应的下标。然后稍微注意一下因为我们所有储存的信息都可以看做是链顶的 \(dp\) 值(因为你的下标已经对应在了链顶处,但是他在 \(i\) 处的 \(dp\) 下标和在链顶处的下标是不同的),故转移和求解还有一些细节需要处理。可能这里讲的不太清楚,具体可以看代码。

至于空间问题,可以直接开指针,每条长链公用一颗线段树即可。

空间复杂度 \(\mathcal{O}(n)\),时间复杂度 \(\mathcal{O}(n\times \log n\times \log V)\)

注意,线段树需要四倍空间,导致你使用指针的时候需要非常精细且小心,我因为没计算好,调了一天。

#include <bits/stdc++.h>
using namespace std;
#define maxn 200005int n, l, r;
int fst[maxn], cnt;
struct node
{int tar, nxt, num;
}arr[maxn << 1];
void adds(int x, int y, int z)
{arr[++cnt].tar = y, arr[cnt].nxt = fst[x], fst[x] = cnt, arr[cnt].num = z;
}
int son[maxn], maxdep[maxn] = {-1};
void dfs(int x, int last)
{int mxid = 0;for (int i = fst[x]; i; i = arr[i].nxt){int j = arr[i].tar;if(j == last) continue;dfs(j, x);if(maxdep[j] > maxdep[mxid]) maxdep[x] = maxdep[j] + 1, mxid = j;}son[x] = mxid;
}
int top[maxn], dep[maxn];
void dfs2(int x, int last, int topf)
{top[x] = topf, dep[x] = dep[last] + 1;if(son[x]) dfs2(son[x], x, topf);for (int i = fst[x]; i; i = arr[i].nxt){int j = arr[i].tar;if(j == son[x] || j == last) continue;dfs2(j, x, j);	}
}
double Dep[maxn];
double *data[maxn << 2], buf[maxn << 2];
int cur = 1;
double mid, ans = 0;
void init(int x, int last)
{for (int i = fst[x]; i; i = arr[i].nxt){int j = arr[i].tar;if(j == last) continue;Dep[j] = Dep[x] + arr[i].num - mid;init(j, x);}
}
void change(int op, int p, int L, int R, int x, double y)
{if(L > x || R < x) return;if(L == R) return data[op][p] = y, void(0);int mid = (L + R) >> 1;change(op, p << 1, L, mid, x, y), change(op, p << 1 | 1, mid + 1, R, x, y);data[op][p] = max(data[op][p << 1], data[op][p << 1 | 1]);
}
double query(int op, int p, int L, int R, int l, int r)
{if(l > r) return -1e17;if(L > r || R < l) return -1e17;if(L >= l && R <= r) return data[op][p];int mid = (L + R) >> 1;return max(query(op, p << 1, L, mid, l, r), query(op, p << 1 | 1, mid + 1, R, l, r));
}
void get_ans(int x, int last)
{if(son[x]){get_ans(son[x], x);ans = max(ans, query(top[x], 1, 0, maxdep[top[x]], max(l + dep[x] - dep[top[x]], 0), min(r + dep[x] - dep[top[x]], maxdep[top[x]])) - Dep[x] + Dep[top[x]]);}change(top[x], 1, 0, maxdep[top[x]], dep[x] - dep[top[x]], Dep[x] - Dep[top[x]]);for (int i = fst[x]; i; i = arr[i].nxt){int j = arr[i].tar;if(j == last || j == son[x]) continue;double k = arr[i].num - mid;data[j] = buf + cur, cur += 4 * (maxdep[j] + 3);get_ans(j, x);for (int i = 0; i <= maxdep[j]; ++i){double now = query(j, 1, 0, maxdep[j], i, i);double Now = query(top[x], 1, 0, maxdep[top[x]], max(l + dep[x] - dep[top[x]] - i - 1, 0), min(r + dep[x] - dep[top[x]] - i - 1, maxdep[top[x]]));ans = max(ans, now + k + Now - Dep[x] + Dep[top[x]]);}for (int i = 0; i <= maxdep[j]; ++i){double now = query(j, 1, 0, maxdep[j], i, i);double Now = query(top[x], 1, 0, maxdep[top[x]], i + dep[x] - dep[top[x]] + 1, i + dep[x] - dep[top[x]] + 1);change(top[x], 1, 0, maxdep[top[x]], i + dep[x] - dep[top[x]] + 1, max(now + Dep[x] - Dep[top[x]] + k, Now));}}
}
int main()
{scanf("%d %d %d", &n, &l, &r);for (int i = 1; i < n; ++i){int x, y, z;scanf("%d %d %d", &x, &y, &z);adds(x, y, z), adds(y, x, z);}dfs(1, 0), dfs2(1, 0, 1);double l = 0, r = 1e6, ans = 0;while(r - l > 1e-4){mid = (l + r) / 2; ::ans = -1, cur = 1;for (int i = 0; i <= 8 * n + 4; ++i) buf[i] = -1e17;data[1] = buf, cur += 4 * (maxdep[1] + 3);init(1, 0);get_ans(1, 0);if(::ans >= 0) ans = mid, l = mid;else r = mid;}printf("%.3lf\n", ans);return 0;
}

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

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

相关文章

zlibrary中文版入口及电子书客户端/app(2024更新)

Z-library是一个全球范围内庞大的数字图书馆之一,其藏书量非常丰富。截至最新数据,Z-library共收录了超过9,826,996册电子书以及84,837,646篇学术期刊文章。这个数字图书馆覆盖了从经典文学巨著到前沿理工学科,从人文艺术瑰宝到专业学术论文的广泛领域,几乎能够满足每一位求…

Playwright:掌握Web自动化测试的新利器

在快速迭代的互联网环境中,Web应用的测试工作日益繁重。传统的手动测试不仅耗时耗力,还难以保证测试的全面性和准确性。面对复杂多变的测试需求,你是否也曾感到力不从心? 别担心!本周四晚上八点,我们特别策划了一场关于Playwright的公开课,旨在帮助大家掌握这款Web自动化…

NOIP2024加赛2

NOIP2024加赛2 题目来源: 2023NOIP A层联测18\(T1\) HZTG5733. 新的阶乘 \(100pts\)预处理素数后直接对 \(1 \sim n\) 进行质因数分解因为有太多冗余枚举导致无法通过。考虑枚举最终形式。具体地,从质因数的角度入手,设当前枚举的质数为 \(p\) ,暴力求出 \(ip\) 中 \(p\) 的…

用处多多!信创PostgreSQL认证证书含金量

PostgreSQL是目前讨论比较多的数据库技术,国内很多大的企业都在开发基于PostgreSQL的数据库产品,比如腾讯云TDSQL-PG版、阿里云PolarDB-PG版、人大金仓等等,考取PostgreSQL数据库证书对个人在数据库领域的职业发展具有多方面的积极作用。以下是对其用处的详细分析: ​ 一、…

南沙C++信奥赛陈老师解一本通题 1225:金银岛

​【题目描述】某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有ss个种类, 每种金属重量不同,分别为n1,n2,...,nsn1,n2,...,ns,同时…

精准、智能、高效:AI平台如何提升医疗数据处理效率50%

思通数科的大模型是一款集成自然语言处理、多模态分析与知识图谱技术的智能系统,专为提升行业信息处理效率和决策支持而设计。该模型依托深度学习与数据驱动,能够在合同审查、智能问答、医疗文本处理等场景中实现精准的文本分类、信息抽取与风险识别。特别在多模态数据处理方…

MySQL 8.0 执行COUNT()很慢原因分析

MySQL 8.0 执行COUNT()很慢原因分析 1.1 问题描述 线上 MySQL8.0.32 环境在执行 SELECT COUNT (1) FROM t0 获取表行数很慢,同样场景下该 SQL 在 MySQL5.7 环境很快就能拿到结果 1.2 问题复现 测试版本:8.0.25 MySQL Community Server - GPL 和 5.7.21-log MySQL Community S…

DAC控制LM358输出4~20ma电路

在带负载0~800Ω左右,电流并不会发生偏差使用注意事项有些时候LM358内部的运放不一定都使用到在使用画PCB和原理图的时候要注意输入端不能直接接地,否则芯片会发烫。并且给出TI的LM358部分说明以及未使用时的处理方法。

mac 关闭所有浏览器的前进后退功能

系统偏好设置 => 触控板 => 更多手势 => 在页面之间轻扫 取消勾选即可。如下图所示:

科陆电子:从卷到赢,连接型CRM助力营销服全链路质、效双飞跃

深圳市科陆电子科技股份有限公司是美的集团旗下企业,于1996年在深圳成立,主板上市企业(2007年在深交所上市,股票代码002121)、国家高新技术企业,拥有国家认定企业技术中心和多个国家级、省级技术中心、实验室。公司主营业务聚焦在智能电网和新型电化学储能两大板块,战略愿景是成…

bug解决记录:前端解密后的中文是问号的解决办法

最近的项目中,遇到了这个问题,我们的容灾环境要进行演练,但是进行切换到容灾环境的时候,发现返回的中文都是?问号 解决思路: 1.先看下接口的请求头和响应头是不是指定了这个编码格式。排查出来发现都是有的 2.看下解密和加密是否有指定编码格式设置字符 byte[] bytes = s…