链接:https://ac.nowcoder.com/acm/contest/8564/I
来源:牛客网
题目描述
scimoon 有一个长度为 n 的数列
一个不幸的事实是,这个数列里的数非常地混乱,scimoon 想让它变得工整
scimoon 现在有 m 种操作,第 i 种操作可以把 [l_i,r_i][l
i
,r
i
] 之间的数全部加一或减一,但是,要使用它就必须先支付 w_iw
i
的费用,然后就可以无限制次数地使用这种操作
scimoon 想要知道,对于任意长度为 n 的数列,是否存在一种选择操作的方式,可以通过使用这些操作,使得所有数列中的数都等于 0
scimoon 并不富有,因此如果有解,他还想要知道最少支付多少费用
输入描述:
第一行两个整数 n,m,表示数列长度和操作个数
接下来 m 行,每行三个整数 l_i,r_i,w_il
i
,r
i
,w
i
,意义见题目描述
输出描述:
如果不存在一种选择操作的方式,输出 -1
否则输出最少支付的费用
示例1
输入
复制
2 3
1 2 3
1 1 100
2 2 101
输出
复制
103
示例2
输入
复制
5 4
1 1 1
2 2 1
3 3 1
4 4 1
输出
复制
-1
备注:
n\le 10^5,m\le 2\times 10^5n≤10
5
,m≤2×10
5
1\le l_i\le r_i\le n,1\le w_i\le 10^91≤l
i
≤r
i
≤n,1≤w
i
≤10
9
因为没有给定数组,所以要求任何一个数组都可以被修改为0,所以要求任何一个区间都可以被修改,设计区间修改,我们可以想到用差分,而差分·,而能修改所有的区间,所以差分需要可以连起来,题目说最小花费,暗示我们可以用最小生成树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10;
int p[N];
struct Edge{
int a, b;
int w;
bool operator<(const Edge &W)const{
return w < W.w;
}
}edge[M];
int find(int x){
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i ++){
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
edge[i] = {a, b + 1, w};
}
sort(edge + 1, edge + 1 + m);
for (int i = 1; i <= n; i ++) p[i] = i;
long long res = 0;
int cnt = 0;
for (int i = 1; i <= m; i ++){
int a = edge[i].a, b = edge[i].b, w = edge[i].w;
int pa = find(a), pb = find(b);
if (pa != pb){
p[pa] = pb;
res += w;
cnt ++;
}
}
if (cnt != n) cout << "-1" << endl;
else cout << res << endl;
return 0;
}