Description

给定一颗 \(n\) 个点的树,带边权。

你可以选出一个包含 \(1\) 顶点的连通块,连通块的权值为连接块内这些点的边权和。

求一种选法,使得这个选法的权值是所有选法中第 \(k\) 小的。如果不存在第 \(k\) 小的那输出最大的。

答案对 \(998244353\) 取模。

Hint

  • \(1\le n,k\le 10^5\)
  • \(\text{边权} \in (0, 10^9]\)

Solution

考虑一个现有的选法,我们考虑如何得到一个新的 尽量小的更大的 选法。

  • 将连通块边缘的一条边换下,用另一条与边缘边相邻的边替换。需要在保证新边的边权不小于旧的情况下,新边权最小。
  • 在边缘新加入一条最小的边。

我们从初始的选法(只有顶点 \(1\))开始,不断按上述策略拓展出新的选法。如果我们每次 优先拓展权值小的,那么在第 \(k\) 次拓展时我们就得到了答案。

那么现在的问题就是每次拓展如何选边。

我们考虑用一个 堆结构 将每个点所有可以拓展出去的边维护起来。

我们将选法视作一个个状态,每个状态都有一个堆维护 所有待拓展的边缘边

那么上述两种策略可以转化为:

  • 删去堆顶,然后换上新的堆顶。很显然就得到了一个次小选法。
  • 选择堆顶对应边另一端的点,表示新拓展的顶点。将该顶点对应出边的边集 合并 到当前堆上。

这里设计到了堆的合并,又不得覆盖原来的信息,那么首选 可持久化左偏树 了。

最后复杂度 \(O((n+k)\log n + k\log k)\)。空间 \(O((n+k)\log n)\)。

Code

/*
* Author : _Wallace_
* Source : https://www.cnblogs.com/-Wallace-/
* Problem : CH 弱省互测 Round #1 OVOO
*/
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue> using namespace std;
const int N = 1e5 + 5;
const int mod = 998244353; int n, k;
int f[N], v[N]; struct Edge {
int to, nxt;
int len;
} e[N];
int head[N], ecnt = 0;
inline void insert(int u, int v, int w) {
e[ecnt] = Edge{v, head[u], w};
head[u] = ecnt++;
} namespace LefT {
struct lef {
int ch[2], dist;
int end, val;
} tr[N << 5];
int total = 0; inline int create(int v, int e) {
int x = ++total;
tr[x] = lef{{0, 0}, 1, e, v};
return x;
}
inline int copy(int x) {
return tr[++total] = tr[x], total;
}
int merge(int x, int y) {
if (!x || !y) return x | y;
if (tr[x].val > tr[y].val) swap(x, y);
int z = copy(x);
tr[z].ch[1] = merge(tr[x].ch[1], y);
if (tr[tr[z].ch[0]].dist < tr[tr[z].ch[1]].dist)
swap(tr[z].ch[0], tr[z].ch[1]);
tr[z].dist = tr[tr[z].ch[1]].dist + 1;
return z;
}
};
int root[N]; void prework(int x) {
using namespace LefT;
for (int i = head[x]; ~i; i = e[i].nxt) {
int y = e[i].to, l = e[i].len;
root[x] = merge(root[x], create(l, y));
prework(y);
}
} struct statu {
int x; long long v;
inline bool operator < (const statu& rhs) const {
return v > rhs.v;
}
}; priority_queue<statu> pq; signed main() {
ios::sync_with_stdio(false);
memset(head, -1, sizeof(head));
cin >> n >> k;
for (int i = 2; i <= n; i++) {
cin >> f[i] >> v[i];
insert(f[i], i, v[i]);
}
prework(1); using namespace LefT;
long long ans = 0ll;
pq.push(statu{root[1], tr[root[1]].val});
for (--k; k && !pq.empty(); --k) {
int x = pq.top().x;
long long val = pq.top().v;
pq.pop(), ans = val; int cur = merge(tr[x].ch[0], tr[x].ch[1]);
if (cur) pq.push(statu{cur, val - tr[x].val + tr[cur].val});
cur = merge(cur, root[tr[x].end]);
if (cur) pq.push(statu{cur, val + tr[cur].val});
} cout << ans % mod << endl;
}

【CH 弱省互测 Round #1 】OVOO(可持久化可并堆)的更多相关文章

  1. 弱省互测#0 t2

    题意 给定两个字符串 A 和 B,求下面四个问题的答案: 1.在 A 的子串中,不是 B 的子串的字符串的数量. 2.在 A 的子串中,不是 B 的子序列的字符串的数量. 3.在 A 的子序列中,不是 ...

  2. 弱省互测#2 t3

    题意 给出\(n\)个01字节和\(m\)个01字节,要求用后者去匹配前者,两个串能匹配当且仅当除了每个字节末位不同,其他位都要相同.问匹配后者至少有多少个末位不同.(\(1 \le m \le n ...

  3. 弱省互测#2 t2

    题意 给两个树,大小分别为n和m,现在两棵树各选一些点(包括1),使得这棵树以1号点为根同构(同构就是每个点的孩子数目相同),求最大的同构树.(n, m<=500) 分析 我们从两棵树中各取出一 ...

  4. 弱省互测#1 t3

    题意 给出一棵n个点的树,求包含1号点的第k小的连通块权值和.(\(n<=10^5\)) 分析 k小一般考虑堆... 题解 堆中关键字为\(s(x)+min(a)\),其中\(s(x)\)表示\ ...

  5. 弱省互测#0 t3

    Case 1 题意 要求给出下面代码的答案然后构造输入. 给一个图, n 个点 m 条边 q 次询问,输出所有点对之间最大权值最小的路径. 题解 把每一个询问的输出看成一条边,建一棵最小生成树. Ca ...

  6. 弱省互测#0 t1

    题意 给一个\(N \times M\)的01网格,1不能走,从起点\((1, 1)\)走到\((N, M)\),每次只能向下或向右走一格,问两条不相交的路径的方案数.(n, m<=1000) ...

  7. 【loj2461】【2018集训队互测Day 1】完美的队列

    #2461. 「2018 集训队互测 Day 1」完美的队列 传送门: https://loj.ac/problem/2461 题解: 直接做可能一次操作加入队列同时会弹出很多数字,无法维护:一个操作 ...

  8. luoguP3769 [CH弱省胡策R2]TATT

    luoguP3769 [CH弱省胡策R2]TATT PS:做这题前先切掉 P4148简单题,对于本人这样的juruo更助于理解,当然dalao就当练练手吧 题目大意: 现在有n个四维空间中的点,请求出 ...

  9. 【2018集训队互测】【XSY3372】取石子

    题目来源:2018集训队互测 Round17 T2 题意: 题解: 显然我是不可能想出来的……但是觉得这题题解太神了就来搬(chao)一下……Orzpyz! 显然不会无解…… 为了方便计算石子个数,在 ...

随机推荐

  1. MySQL架构(面)

    和其它数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用.主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离.这种架构可 ...

  2. C/C++中内存对齐问题的一些理解(转)

    内存对齐指令 一般来说,内存对齐过程对coding者来说是透明的,是由编译器控制完成的 如对内存对齐有明确要求,可用#pragma pack(n)指定,以n和结构体中最长数据成员长度中较小者为有效值 ...

  3. Debian 64位内核升级步骤

    安装相关依赖包 apt-get install bzip2 libncurses5-dev kernel-package zlib1g-dev gcc make kernel-package wget ...

  4. sublime 3 phpfmt配置(大括号对齐)

    默认选项:  default: phpfmt.sublime-settings:         {         "version": 2,         "php ...

  5. html2image

    测试没有,生产有 也就是写死的显示,配置的不显示

  6. How to realize one's ambition

    Work Overtime Can it work? To some extent, it parhaps works very well. What if you do little job and ...

  7. MyBatis学习02

    3.增删改查实现 select select标签是mybatis中最常用的标签之一 select语句有很多属性可以详细配置每一条SQL语句 SQL语句返回值类型.[完整的类名或者别名] 传入SQL语句 ...

  8. vue 2.9.6升级到3X版本

    先通过 npm uninstall vue-cli -g 卸载vue,然后再安装,但是vue -V时依然是2.9.6版本: 第一步: npm config get registry 第二步: npm ...

  9. H5 ,Css实现了你的logo

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. Java继承的两道实验题目

    设计一个表示二维平面上点的类Point,包含有表示坐标位置的Protect类型的成员变量 获取和设置x和y值的public方法 package classwork_6; public class Po ...