\(\mathcal{Description}\)

  Link.

  给定一棵 \(n\) 个结点的树,边有边权,对于每个整数 \(x\in[0,n)\),求出最少的删边代价使得任意结点度数不超过 \(x\)。

  \(n\le2.5\times10^5\)。

\(\mathcal{Solution}\)

  从单个询问入手,设此时 \(x\) 为常数,就有一个简单的树上 DP。令 \(f(u,0/1)\) 表示 \(u\) 点与父亲的边不断 / 断时,\(u\) 子树内的最小代价。以 \(f(u,0)\) 为例,设 \(v\) 是 \(u\) 的儿子,转移相当于强制选择至少 \(\max\{0,d_u-x\}\) 个 \(f(v,1)\) 进行转移。先特判掉 \(f(v,1)+\operatorname{cost}(u,v)\le f(v,0)\) 的 \(v\),此时用 \(f(v,1)+\operatorname{cost}(u,v)\) 的代价断边显然更优。此后,先仅用 \((v,0)\) 转移,把 \(f(v,1)+\operatorname{cost}(u,v)-f(v,0)\) 压入大根堆。保留堆最后 \(\max\{0,d_u-x\}\) 个元素并加入贡献就行啦。

  接下来,按 \(x\) 从 \(0\) 到 \(n-1\) 的顺序考虑询问。可以发现,在 \(x\) 增大的过程中,某些点的度数不超过 \(x\),那么 \(x\) 对这些点就再也没有限制了。那么强行把这个点拉到叶子,将它的 DP 信息压入邻接点的堆,再暴力跑 DP 就解决了。

  复杂度 \(\mathcal O(n\log n)\)。

\(\mathcal{Code}\)

#pragma GCC optimize( 2 )

#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm> typedef long long LL; const int MAXN = 2.5e5;
int n, ecnt, head[MAXN + 5], deg[MAXN + 5], vis[MAXN + 5];
LL f[MAXN + 5][2];
std::pair<int, int> order[MAXN + 5];
bool kill[MAXN + 5]; inline char fgc () {
static char buf[1 << 17], *p = buf, *q = buf;
return p == q && ( q = buf + fread ( p = buf, 1, 1 << 17, stdin ), p == q ) ? EOF : *p ++;
} inline int rint () {
int x = 0; char d = fgc ();
for ( ; d < '0' || '9' < d; d = fgc () );
for ( ; '0' <= d && d <= '9'; d = fgc () ) x = x * 10 + ( d ^ '0' );
return x;
} inline void wint ( const LL x ) {
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
} std::vector<LL> pmem, rmem;
std::vector<std::pair<int, int> > gr[MAXN + 5]; struct RemovableHeap {
int siz; LL sum;
std::priority_queue<LL> ele, rem;
RemovableHeap (): siz ( 0 ), sum ( 0 ) {}
inline void snap () { pmem.clear (), rmem.clear (); }
inline void nspush ( const LL x ) { ++ siz, sum += x, ele.push ( x ); }
inline void nspop ( const LL x ) { -- siz, sum -= x, rem.push ( x ); }
inline void nspop () { -- siz, sum -= top (), ele.pop (); }
inline void push ( const LL x ) { nspush ( x ), pmem.push_back ( x ); }
inline void pop ( const LL x ) { nspop ( x ), rmem.push_back ( x ); }
inline void pop () { -- siz, sum -= top (), rmem.push_back ( top () ), ele.pop (); }
inline int size () { return siz; }
inline LL top () {
for ( ; ! ele.empty () && ! rem.empty () && ele.top () == rem.top (); ele.pop (), rem.pop () );
return ele.top ();
}
inline void recov () {
for ( LL p: pmem ) nspop ( p );
for ( LL r: rmem ) nspush ( r );
pmem.clear (), rmem.clear ();
}
} heap[MAXN + 5]; inline void solve ( const int u, const int x, const int fa ) {
vis[u] = x; int wait = deg[u] - x;
for ( ; heap[u].size () > wait; heap[u].nspop () );
for ( auto v: gr[u] ) {
if ( v.first == fa ) continue;
if ( deg[v.first] <= x ) break;
solve ( v.first, x, u );
}
heap[u].snap ();
LL bas = 0;
for ( auto v: gr[u] ) {
if ( v.first == fa ) continue;
if ( deg[v.first] <= x ) break;
LL dt = f[v.first][1] + v.second - f[v.first][0];
if ( dt <= 0 ) { -- wait, bas += f[v.first][1] + v.second; continue; }
bas += f[v.first][0], heap[u].push ( dt );
}
for ( ; heap[u].size () && heap[u].size () > wait; heap[u].pop () );
f[u][0] = bas + heap[u].sum;
for ( ; heap[u].size () && heap[u].size () > wait - 1; heap[u].pop () );
f[u][1] = bas + heap[u].sum;
heap[u].recov ();
} int main () {
n = rint ();
LL ws = 0;
for ( int i = 1, u, v, w; i < n; ++ i ) {
u = rint (), v = rint (), w = rint ();
++ deg[u], ++ deg[v], ws += w;
gr[u].push_back ( { v, w } );
gr[v].push_back ( { u, w } );
}
wint ( ws );
for ( int i = 1; i <= n; ++ i ) {
order[i] = { deg[i], i };
sort ( gr[i].begin (), gr[i].end (),
[]( const std::pair<int, int> a, const std::pair<int, int> b ) {
return deg[a.first] > deg[b.first];
}
);
}
std::sort ( order + 1, order + n + 1 );
for ( int x = 1, dis = 1; x < n; ++ x ) {
for ( int u; dis <= n && order[dis].first == x; ++ dis ) {
kill[u = order[dis].second] = true;
for ( auto v: gr[u] ) {
if ( deg[v.first] <= x ) break;
heap[v.first].nspush ( v.second );
}
}
LL ans = 0;
for ( int i = dis, u; i <= n; ++ i ) {
if ( vis[u = order[i].second] ^ x ) {
solve ( u, x, 0 );
ans += f[u][0];
}
}
putchar ( ' ' ), wint ( ans );
}
putchar ( '\n' );
return 0;
}

Solution -「CF 1119F」Niyaz and Small Degrees的更多相关文章

  1. Solution -「CF 1342E」Placing Rooks

    \(\mathcal{Description}\)   Link.   在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...

  2. Solution -「CF 1622F」Quadratic Set

    \(\mathscr{Description}\)   Link.   求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...

  3. Solution -「CF 923F」Public Service

    \(\mathscr{Description}\)   Link.   给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...

  4. Solution -「CF 923E」Perpetual Subtraction

    \(\mathcal{Description}\)   Link.   有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...

  5. Solution -「CF 1586F」Defender of Childhood Dreams

    \(\mathcal{Description}\)   Link.   定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...

  6. Solution -「CF 1237E」Balanced Binary Search Trees

    \(\mathcal{Description}\)   Link.   定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...

  7. Solution -「CF 623E」Transforming Sequence

    题目 题意简述   link.   有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...

  8. Solution -「CF 1023F」Mobile Phone Network

    \(\mathcal{Description}\)   Link.   有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...

  9. Solution -「CF 599E」Sandy and Nuts

    \(\mathcal{Description}\)   Link.   指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...

随机推荐

  1. 阿里云服务器ECS Ubuntu16.04 初次使用配置教程(图形界面安装)

    原文链接:? 传送门 前一阵子购买了阿里云的云服务器ECS(学生优惠),折腾了一阵子后对有些东西不太满意,所以就重新初始化了磁盘,刚好要重新安装图形界面,于是就顺手写了这么一篇文章. 第一次登陆服务器 ...

  2. PAT 乙级 1004. 成绩排名 (20)(C语言描述)

    读入n名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓名和学号. 输入格式:每个测试输入包含1个测试用例,格式为 第1行:正整数n 第2行:第1个学生的姓名 学号 成绩 第3行:第2个学生 ...

  3. 大数据安全与RANGER学习和使用

    概述 再说ranger之前需要明白一下大数据的安全体系的整体介绍,安全体系其实也就是权限可控,先说说权限:权限管理的目标,绝对不是简单的在技术层面建立起用户,密码和权限点的映射关系这么简单的事,更重要 ...

  4. 解决twrp中内部存储为0MB的情况

    本来打算给备用机红米4a刷个dotos的系统,结果忘记双清就刷了,然后进去系统也是直接黑屏,很神奇的是长按电源键能弹出dotos的关机选项.然后进去twrp准备双清在刷时,发现内部存储变成了0MB,然 ...

  5. ThinkPad S5立体声混响以及语音识别

    smartaudio里面改成语音识别就可以是立体声混响了.但是微软语音识别在国内依然不好用,微软服务在国内太卡了. (联想总是多此一举,各种乱起八糟的软件,给用户造成困难,以前老机子驱动无线网卡锁在L ...

  6. Ajax_GET的一个基本用法

    Ajax_GET的一个基本用法 首先先创建一个Server.js文件 ​//1.引入express// const { response } = require('express');const ex ...

  7. 一文读懂 HTTP/1HTTP/2HTTP/3

    转自 https://zhuanlan.zhihu.com/p/102561034

  8. Sping简介

    SSH:Struct2 + Spring +Hibernate SSM:SpringMVC + Spring + Mybatis 优点 1,Sping是一个开源的免费的框架(容器) 2,Spirng是 ...

  9. Apple历代Mac系统汇总

    编号 系统名 版本号 名称 发布时间 01 macOS 11.0 Big Sur(大惊喜) 2020年6月 02 macOS 10.15 Catalina(卡特琳娜) 2019年9月 03 macOS ...

  10. Redis学习笔记(二)redis 底层数据结构

    在上一节提到的图中,我们知道,可以通过 redisObject 对象的 type 和 encoding 属性.可以决定Redis 主要的底层数据结构:SDS.QuickList.ZipList.Has ...