C - Decrement on the Tree
题意: 给你一颗有边权的无根树,你可以每次选取一条路径使得该路径上所有的边权减少1,现在有q次修改询问使得所有边权变为0的最少操作次?
思路: 由于有多次询问,所以每次修改询问,我们要做到复杂度为O(1)或者O(logn),所以比赛的时候一直在想有什么数据结构可以维护路径。但是这道题你需要将其转化一下,他就变得容易了。题目可以转化成算每个点作为路径端点的贡献,这样只需要算每个端点的贡献了。
接下来如何算每个端点的贡献呢?
考虑与一个点所有相连的边总权值与最大权值,要使得这个点不作为端点,我们每次最优选取两条边为同一条路径,所有就会出现三种情况:
1)相邻边权的最大值(max)大于其余剩下的相邻边权总和(rest),贡献为max-rest
2)相邻边权的最大值小于其余剩下的相邻边权总和且该点所有相邻边总边权为奇数,贡献为1
3)相邻边权的最大值小于其余剩下的相邻边权总和且该点所有相邻边总边权且为偶数,贡献为0
这样我们就能算每个点的贡献了,但是如何能做到快速修改呢
我们可以使用stl中的multiset进行修改即可
因为我们算出所有点的总贡献,一条路径有两个端点,所有最终得到的答案需要/2
代码:
#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<stack>
#include<queue>
#define INF 0x3f3f3f3f
#define lowbit(x) x & -x
#define lson root<<1,l,mid
#define rson root<<1|1,mid+1,r
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+5;
struct node{
int u,v,w;
}edge[N];
ll sum[N];
multiset<int> s[N];
ll ans;
ll get(int x){
auto t=s[x].end();
t--;
if(*t>sum[x]-*t)return *t-(sum[x]-*t);
if(sum[x]%2==1)return 1;
return 0;
}
int main(){
#ifdef Mizp
freopen("in.txt","r",stdin);
#endif
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<n;i++){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
sum[edge[i].u]+=edge[i].w;
sum[edge[i].v]+=edge[i].w;
s[edge[i].u].insert(edge[i].w);
s[edge[i].v].insert(edge[i].w);
}
//cout<<get(2)<<endl;
for(int i=1;i<=n;i++)
ans+=get(i);
printf("%lld\n",ans/2);
while(q--){
int p,w;
scanf("%d%d",&p,&w);
ans-=get(edge[p].u);ans-=get(edge[p].v);
s[edge[p].u].erase(s[edge[p].u].lower_bound(edge[p].w));
s[edge[p].v].erase(s[edge[p].v].lower_bound(edge[p].w));
sum[edge[p].u]-=edge[p].w;sum[edge[p].v]-=edge[p].w;
edge[p].w=w;
sum[edge[p].u]+=edge[p].w;sum[edge[p].v]+=edge[p].w;
s[edge[p].u].insert(w);s[edge[p].v].insert(w);
ans+=get(edge[p].u);ans+=get(edge[p].v);
printf("%lld\n",ans/2);
}
return 0;
}
I - Tournament
题意: 现在有 n 个队伍参加比赛,任意两个队伍之间都要进行一次比赛,也就是共需要进行 n * ( n - 1 ) / 2 次比赛,对于每个队伍来说,必须要在第一场比赛的时候到达赛场,在最后一场比赛结束后离开赛场,在赛场上呆的时间即为贡献,现在求出一种比赛的安排顺序,使得每个队伍的贡献之和最小
思路: 构造题,比赛构造了很久也构造不出来,具体思路请参考他人优秀题解
代码:
#include<bits/stdc++.h>
#include<iostream>