\(\mathcal{Description}\)

  Link.

  给定一棵含 \(n\) 个结点的树,双向边权不相同。\(q\) 次询问,每次询问在树上标记 \(e\) 个点,标记的价值为所有趋向于某个标记点的有向边权值之和,求价值的最大值。

  \(q\le n\le2\times10^5\)。

\(\mathcal{Solution}\)

  \(e=1\text{ or }2\) 的时候可以直接换根求解。需要强调的是,当确定一个被标记的根时,其余标记点的贡献为根到这个标记点的有向路径长度(取并)。接下来引入一些结论。首先有:

  对于一棵根被钦定标记的树(\(e=1\)),当 \(e=k<n\) 时,一定能通过标记深度最深的结点使得其成为 \(e=k\) 时的最优解。

  不难意会。(

  由此可以推出一个关键的结论:

  对于 \(k>2\),\(e=k\) 时的最优解必然通过在某个 \(e=k-1\) 时的最优解的基础上新标记一个点得到。

  记 \(e=k\) 时某个最优解标记点集合为 \(S\),\(e=k+1\) 时任一最优解的标记点集合为 \(T\),考虑反证,若不存在 \(S\sub T\):

  • 若 \(S\cap T\neq\varnothing\),取一个 \(r\in S\cap T\),标记并作为树根。由上一个结论,矛盾。
  • 若 \(S\cap T=\varnothing\),考虑把 \(T\) 中的一个结点丢到 \(S\) 中,此时 \(S\) 不会比 \(T\) 劣。

  所以,以 \(e=2\) 时的一个标记点为根,令每片叶子的权值为其保持作为子树最深点,向上能爬的距离。排序取前 \(k\) 大之和加上一些常数就是 \(e=k\) 的答案。复杂度 \(\mathcal O(n\log n)\)。

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#include <algorithm> #define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i ) typedef long long LL;
typedef std::pair<int, LL> PIL; inline int rint() {
int x = 0, s = getchar();
for ( ; s < '0' || '9' < s; s = getchar() );
for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
return x;
} template<typename Tp>
inline void wint( Tp x ) {
if ( x < 0 ) putchar( '-' ), x = -x;
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} inline LL lmax( const LL a, const LL b ) { return a < b ? b : a; }
inline void chkmax( LL& a, const LL b ) { a < b && ( a = b, 0 ); } const int MAXN = 2e5;
const LL LINF = 1ll << 60;
int n, ecnt = 1, head[MAXN + 5], rt;
LL all, upsum, wgt[MAXN + 5];
struct Edge { int to, val, nxt; } graph[MAXN * 2 + 5]; inline void link( const int s, const int t, const int w ) {
graph[++ecnt] = { t, w, head[s] };
head[s] = ecnt;
} namespace Subtask23 { int siz[MAXN + 5], root;
LL sum[MAXN + 5], mx[MAXN + 5], sm[MAXN + 5], ans[2]; inline void init( const int u, const int fa ) {
siz[u] = 1, mx[u] = 0, sm[u] = -LINF;
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ fa ) {
init( v, u );
siz[u] += siz[v], sum[u] += sum[v] + graph[i ^ 1].val;
LL d = mx[v] + graph[i].val;
if ( mx[u] < d ) sm[u] = mx[u], mx[u] = d;
else if ( sm[u] < d ) sm[u] = d;
}
}
} inline void solve( const int u, const int fa, const LL ups, const LL upx ) {
chkmax( ans[0], sum[u] + ups );
LL tmp = sum[u] + ups + lmax( upx, mx[u] );
if ( ans[1] < tmp ) root = u, ans[1] = tmp;
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ fa ) {
int w1 = graph[i].val, w2 = graph[i ^ 1].val;
LL ns = ups + sum[u] - sum[v] - w2 + w1;
LL nx = lmax( upx, mx[v] + w1 < mx[u] ? mx[u] : sm[u] ) + w2;
solve( v, u, ns, nx );
}
}
} inline void main() {
init( 1, 0 );
solve( 1, 0, 0, 0 );
} } // namespace Subtask23. inline PIL init( const int u, const int fa ) {
PIL ret( u, 0 );
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ fa ) {
PIL tmp( init( v, u ) );
upsum += graph[i ^ 1].val;
wgt[tmp.first] += graph[i].val;
if ( tmp.second + graph[i].val > ret.second ) {
ret = { tmp.first, tmp.second + graph[i].val };
}
}
}
return ret;
} int main() {
freopen( "city.in", "r", stdin );
freopen( "city.out", "w", stdout );
n = rint();
rep ( i, 2, n ) {
int u = rint(), v = rint(), a = rint(), b = rint();
all += a + b;
link( u, v, a ), link( v, u, b );
}
Subtask23::main();
rt = Subtask23::root;
init( rt, 0 );
// printf( "root is %d: ", rt );
// rep( i, 1, n ) printf( "%lld ", wgt[i] );
// puts( "" );
std::sort( wgt + 1, wgt + n + 1, []( const LL a, const LL b ) {
return a > b;
} );
rep( i, 1, n ) wgt[i] += wgt[i - 1];
for ( int q = rint(), e; q--; ) {
e = rint();
wint( all - ( e < 2 ? Subtask23::ans[0] :
upsum + wgt[e - 1] ) ), putchar( '\n' );
}
return 0;
}

Solution -「JOISC 2019」「LOJ #3036」指定城市的更多相关文章

  1. 【LOJ】#3036. 「JOISC 2019 Day3」指定城市

    LOJ#3036. 「JOISC 2019 Day3」指定城市 一个点的可以dp出来 两个点也可以dp出来 后面的就是在两个点的情况下选一条最长的链加进去,用线段树维护即可 #include < ...

  2. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  3. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

  4. 【LOJ】#3033. 「JOISC 2019 Day2」两个天线

    LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...

  5. 【LOJ】#3031. 「JOISC 2019 Day1」聚会

    LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...

  6. 【LOJ】#3030. 「JOISC 2019 Day1」考试

    LOJ#3030. 「JOISC 2019 Day1」考试 看起来求一个奇怪图形(两条和坐标轴平行的线被切掉了一个角)内包括的点个数 too naive! 首先熟练的转化求不被这个图形包含的个数 -- ...

  7. 「JOISC 2019 Day3」穿越时空 Bitaro

    「JOISC 2019 Day3」穿越时空 Bitaro 题解: ​ 不会处理时间流逝,我去看了一眼题解的图,最重要的转换就是把(X,Y)改成(X,Y-X)这样就不会斜着走了. ​ 问题变成二维平面上 ...

  8. @loj - 3039@ 「JOISC 2019 Day4」蛋糕拼接 3

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 今天是 IOI 酱的生日,所以她的哥哥 JOI 君给她预定了一个 ...

  9. 「JOISC 2019 Day4」蛋糕拼接 3

    loj 3039 NKOJ Description \(n\)个蛋糕,每个蛋糕有\(w_i,h_i\).选\(m\)个蛋糕满足\(\sum\limits_{j=1}^mw_{k_j}-\sum\lim ...

随机推荐

  1. java 多态 总结

    1.前言 引用教科书解释: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 通俗来说: 总结:多态的抽象类与接口有点相似: 父类不需要具体实现方 ...

  2. spring boot + spring security +前后端分离【跨域】配置 + ajax的json传输数据

    1.前言 网上各个社区的博客参差不齐 ,给初学者很大的困扰 , 我琢磨了一天一夜,到各个社区找资料,然后不断测试,遇到各种坑,一言难尽啊,要么源码只有一部分,要么直接报错... 最后实在不行,直接去看 ...

  3. centos 内存使用情况+负载使用情况

    内存使用情况,查看内存 free -h #查看内存 available:  可用内存 buff/cache:   缓存内存 free:   空闲内存 used: 已使用内存 负载使用情况 cat /p ...

  4. Java定时调度

    一.实现方式 Timer:单线程,串行: ScheduledExecutor:并行,论询,实现麻烦: Spring Scheduler:适合小任务: JcronTab:按照crontab语法编写的ja ...

  5. 应用层:http请求报文和响应报文

    1.http请求报文 请求报文由请求行.报文头.空行.报文体组成. 请求行可分为请求方法.请求URL.HTTP协议及版本. 举例1: GET / HTTP/1.1\nHost: 220.181.38. ...

  6. spring是线程安全的吗

    spring默认bean是单例无状态的,我们交给spring管理的service,controller都是一个单例的bean,也就是说多个线程共享一个实例. 如果你在这种类里写成员变量,那这个变量的访 ...

  7. 网络编程-TCP连接的建立与终止

    TCP是一个面向连接的协议.无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接. 1.建立连接 请求端(通常称为客户)发送一个 SYN 段指明客户打算连接的服务器的端口,以及初始序号( I ...

  8. 【解决了一个小问题】golang go.mod中多了一个斜杠导致replace无效

    replace github.com/sxxx/common_lib/src/ => ../../common_lib/src 修改成 replace github.com/sxxx/commo ...

  9. 分享一个学习cesiumjs的中文社区

    在cesiumjs中文社区的时间线中我写到: 2018年10月10日 注册用户数51,日uv破100 Mark截图 2018年06月22日 上线测试 2018年06月19日 获得cesiumcn.or ...

  10. 工作自动化,替代手工操作,使用python操作MFC、windows程序

    目录 背景--为什么要自动化操作? 方法--怎么实现自动化操作? 查找窗体 发送消息 获取文本 总结 背景--为什么要自动化操作? 工作中总是遇到反复重复性的工作?怎么用程序把它变成自动化操作?将程序 ...