欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

牛客(多校10)B:Decrement on the Tree

程序员文章站 2022-06-02 22:41:20
...

牛客(多校10)B:Decrement on the Tree
示例
输入:

5 3
1 2 3
1 3 4
2 4 5
3 5 6
1 10
2 10
3 10

输出

8
12
10
10

题目:

你得到了一棵树。有n个顶点和n-1边.树的每一个边缘都有一个非负的权重。每次,你可以选择两个不同的顶点u,v,并减去路径上每条边的权重1,你想使所有边的权重变为零。
最小操作次数是多少?
您还需要支持修改边权:将p边的权重更改为w,每次修改后需要输出答案。

提前注释:multiset是< set >库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,而且序列中可以存在重复的数。
代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll sum[100100],v[100100],w[100100],p[100100],x,y,n,m,i,j,k,l,o;
multiset<ll>s[100100];
multiset<ll>::iterator it;
ll ans;
ll ga(ll x)
{
	it=--(s[x].end());
	if (*it>sum[x]-*it) return *it*2-sum[x];
	return sum[x]&1;
}
void jia(ll i)
{
	ans-=ga(i);
	sum[i]+=y-p[x];
	s[i].erase(s[i].find(p[x]));
	s[i].insert(y);
	ans+=ga(i);
}
int main()
{
	scanf("%lld%lld",&n,&m);
	for (i=1;i<n;i++)
	{
		scanf("%lld%lld%lld",&v[i],&w[i],&p[i]);
		sum[v[i]]+=p[i];
		sum[w[i]]+=p[i];
		s[v[i]].insert(p[i]);
		s[w[i]].insert(p[i]);
	}
	for (i=1;i<=n;i++)
	 ans+=ga(i);
	printf("%lld\n",ans/2);
	for (i=1;i<=m;i++)
	{
		scanf("%lld%lld",&x,&y);
		jia(v[x]);
		jia(w[x]);
		p[x]=y;
		printf("%lld\n",ans/2);
	}
}
相关标签: ACM