【Comet OJ - Contest #8 F 黄金体验】【lct】

该博客讨论了一道竞赛题目,涉及一棵带有初始权重的树,要求支持节点权值的增减操作以及寻找包含指定数量节点的最大联通子图点权和。当k等于2时,问题转化为找最长带权路径。通过分析,博主提出解决方案利用LCT(Link-Cut Tree)数据结构进行长链剖分,并在维护过程中处理点权变化。实现中需要注意在访问直径时选择较大权重的一端作为根节点,以及记录每条链的权重。
摘要由CSDN通过智能技术生成

题意

有一棵 n n n个节点的树,每个点有一个初始权值 w i w_i wi,要求支持两种操作:
1、使 x x x的点权增加 y y y
2、给出 k k k,选定 k k k个点使得包含这 k k k个点的最小联通子图点权和最大,你只需要输出这个最大值。
n , q ≤ 1 0 5 n,q\le10^5 n,q105

分析

k = 2 k=2 k=2,显然选的是带权最长链。
可以发现 k k k每增加 1 1 1,新的答案显然是在原来最优方案的基础上,新加入一个叶节点。
暴力的做法是先找到带权最长链,使链上点的点权变为 0 0 0,然后每次找从直径端点开始的最长链,再把最长链上点权变为 0 0 0.
可以发现这个过程实际上就是从带权直径的一个端点为根作长链剖分,然后选出前 k k k大的链作为答案。
可以用lct来维护长链剖分,每次更新点权后,不断往上更新长链,相当于lct的access操作。
由于必须要以带权直径的端点作为根,所以修改点权后可能要进行换根操作。具体实现的时候可以在access到直径的时候,选出对应点较大的一端包含的端点换为根,然后正常维护即可。
还要用数据结构来记录每一条链的权值。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>

typedef long long LL;

const int N=100005;
const LL inf=(LL)1e14;

int n,q,rt,cnt,last[N];
LL dis[N],w[N],rtd;
struct tree{
   int l,r,s,fa;LL w;bool rev;}t[N];
struct edge{
   int to,next;}e[N*2];
std::multiset<LL> se;
std::multiset<LL>::iterator it;

struct Segtree
{
   
	int rt,sz;
	struct tree{
   int l,r,s;LL w;}t[N*80];
	
	void ins(int &d,LL l,LL r,LL x,int y)
	{
   
		if (!d) d=++sz;
		t[d].s+=y;t[d].w+=x*y;
		if (l==r) return
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值