原题链接
题目描述
思路
对于“相等”的约束条件,易得,可将每个 x 看作一个点,每个“相等”的条件看作两个点的一条边,然后将所有 x 就分成无向图中的若干个集合。
用并查集维护这些集合。先处理所有“相等”的条件,合并每两个 x 的集合。然后遍历“不等”的条件,如果存在两个x处于同一集合,那么就不可被满足,输出“NO”;若不存在,则可以被满足,输出“YES”。
但是,本题 x 的范围是 1 <= x <= 1e9,需要用到离散化的技巧。把变量 x 的范围映射到1 ~ 2n之内,再用上述算法解决。
离散化
就是把无穷大集合中的若干个元素映射为有限集合。
有时候,数据范围虽然定义在整数集合 Z,但是只涉及其中 m 个有限数值,并且与数值的绝对大小无关。离散化就是把整数集合 Z 中的这 m 个数与1 ~ m建立映射关系。
a 原数组
b 离散化后的数组
sort(a + 1, a + n + 1); // 排序
int m = unique(a + 1, a + n + 1) - a; // 去重
查询 x 离散化后到 1 ~ m 的整数
lower_bound(a + 1, a + m + 1, x) - a;
并查集
初始化
for (int i = 1; i <= n; i ++ )
p[i] = i;
查集
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
并集
p[find(x)] = find(y);
完整Code
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int p[N];
int n, b[N];
struct Node {
int x1, x2, e;
} a[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
int T; cin >> T;
while (T -- )
{
// 别忘了初始化
memset(b, 0, sizeof b);
memset(p, 0, sizeof p);
memset(a, 0, sizeof a);
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i].x1 >> a[i].x2 >> a[i].e;
b[i * 2 - 1] = a[i].x1;
b[i * 2] = a[i].x2;
}
// 离散化
sort(b + 1, b + n * 2 + 1);
int m = unique(b + 1, b + 2 * n + 1) - b;
for (int i = 1; i <= n; i ++ )
{
a[i].x1 = lower_bound(b + 1, b + m + 1, a[i].x1) - b;
a[i].x2 = lower_bound(b + 1, b + m + 1, a[i].x2) - b;
}
for (int i = 1; i <= m; i ++ )
p[i] = i;
// 并集
for (int i = 1; i <= n; i ++ )
if (a[i].e) p[find(a[i].x1)] = find(a[i].x2);
// 检验是否可以被满足
bool f = true;
for (int i = 1; i <= n; i ++ )
if (!a[i].e && find(a[i].x1) == find(a[i].x2))
{
cout << "NO" << endl;
f = false; break ;
}
if (f) cout << "YES" << endl;
}
return 0;
}