牛客(多校10)B:Decrement on the Tree
程序员文章站
2022-06-02 22:41:20
...
示例
输入:
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);
}
}
推荐阅读
-
牛客多校第三场 A-Clam and Fish【贪心】+ B-Classical String Problem【思维】
-
2020牛客暑期多校 第二场 B Boundary(计算几何)
-
2020牛客暑期多校训练营(第一场)B Infinite Tree 虚树
-
2020牛客暑期多校第二场 C - Cover the Tree(思维/贪心)
-
C.Decrement on the Tree .2020牛客暑期多校训练营(第十场)
-
2020牛客多校第十场C-Decrement on the Tree
-
2020牛客多校十C-Decrement on the Tree
-
牛客(多校10)B:Decrement on the Tree
-
2020暑期牛客多校训练营第十场(C)Decrement on the Tree(图论,set)
-
2020牛客暑期多校训练营Decrement on the Tree(图论,set)