题意:
有一个长度为n的数列,一共有m句话,每句话都有a,b,c,代表在[a,b]区间内的数的和。其中有一些话是真的,有一些话是假的(与原来的事实冲突的),问给出这些话中有几句是假的。
思路:
是一道并查集的题目。
其中用uf[n]代表n的父亲,用dis[n]代表n到uf[n]之间的数字之和。
那么对于f1 = find(a), f2 = find(b).
如果f1 < f2,那么会有两种情况。
第一种:a <= b <= f1 <= f2:
那么uf[f1] = f2,就有
dis[f1] = dis[b] - (dis[a] - c);
第二种:a <= f1 <= b <= f2:
和上面相同。
如果f1 > f2,那么只会有一种情况:a <= b <= f2 <= f1
那么uf[f2] = f1,就有
dis[f2] = dis[a] - dis[b] - c;
如果f1 == f2,那么就可以通过dis[a] - dis[b] 是否等于c来判断话的对错。
Code:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<list>
#include<map>
#include<set>
#define TEST
#define LL long long
#define Mt(f, x) memset(f, x, sizeof(f));
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#ifdef TEST
#define See(a) cout << #a << " = " << a << endl;
#define See2(a, b) cout << #a << " = " << a << ' ' << #b << " = " << b << endl;
#define debug(a, s, e) rep(_i, s, e) {cout << a[_i] << ' ';} cout << endl;
#define debug2(a, s, e, ss, ee) rep(i_, s, e) {debug(a[i_], ss, ee)}
#else
#define See(a)
#define See2(a, b)
#define debug(a, s, e)
#define debug2(a, s, e, ss, ee)
#endif // TEST
const int MAX = 2e9;
const int MIN = -2e9;
const double eps = 1e-8;
const double PI = acos(-1.0);
using namespace std;
const int N = 200000 + 5;
int uf[N], dis[N];
void init(int n)
{
for(int i = 0; i <= n; ++i)
{
uf[i] = i;
dis[i] = 0;
}
}
int fd(int n)
{
if(n != uf[n])
{
int t = uf[n];
uf[n] = fd(uf[n]);
dis[n] += dis[t];
}
return uf[n];
}
int make(int a, int b, int c)
{
int f1 = fd(a);
int f2 = fd(b);
if(f1 == f2)
{
if(dis[a] - dis[b] == c)
{
return 0;
}
return 1;
}
else if(f1 < f2)
{
uf[f1] = f2;
dis[f1] = dis[b] - (dis[a] - c);
}
else
{
uf[f2] = f1;
dis[f2] = dis[a] - dis[b] - c;
}
return 0;
}
int main()
{
int n, q;
while(~scanf("%d%d", &n, &q))
{
init(n);
int ans = 0;
while(q--)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
ans += make(a - 1, b, c);//这里为[a - 1, b]可以使相邻的区间连接在一起。
}
printf("%d\n", ans);
}
return 0;
}
/*
3 10
1 3 10
1 1 1
1 2 3
3 3 8
3 3 7
*/