小 SX 真的是辣鸡极了,这么水的题还能卡好久。
小 SX 平时用的 OJ 是洛谷,这道题我 AW 是没交的,我用某谷交的,A 了。
闲话少说,切入正题——
显然这道题我们可以用并查集来写为什么,看标签。
本来我想的是区域并查集,分两块,其实完全没必要。
对于相等的 $x_i$ 和 $x_j$ 我们就将 $i$ 和 $j$ 直接合并,表示两数相等。
对于不相等的 $x_i$ 和 $x_j$,我们就查询两数是否在同一个集合,如果在,说明不成立,直接输出 NO
。
这道题其实还有一些小坑,我们一定要先处理 $e = 1$ 的条件,如果您写的是一起处理,有一个数据可以 hack 掉:
1
1
1 2 0
1 2 1
显然输出的是 NO
,结果是 YES
。
还有一点,由于 $i \le j \le 10 ^ 9$,所以我们要离散化一下。
离散化会把,就是排序去重二分找一下就没了。
上代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#define MAXN 1000000
using namespace std;
int l[MAXN * 2 + 10], fa[MAXN * 2 + 10], len;
bool e[MAXN + 10];
struct node{
int a, b, e;
}T[MAXN + 10];
bool cmp(node x, node y) {//把 e = 1 的放前面
return x.e > y.e;
}
int Find(int x) {//并查集找
if(fa[x] == x) return x;
else return fa[x] = Find(fa[x]);
}
void Union(int x, int y) {//并查集并
int X = Find(x), Y = Find(y);
if(X != Y) fa[Y] = X;
}
int G(int x) {//离散化找
return lower_bound(l + 1, l + len + 1, x) - l;
}
int main() {
int t, n;
cin >> t;
while(t--) {
len = 0;
memset(l, 0, sizeof(l));
cin >> n;
for(int p = 1; p <= 2 * n; p++)
fa[p] = p;
for(int p = 1; p <= n; p++) {
cin >> T[p].a >> T[p].b >> T[p].e;
l[p * 2 - 1] = T[p].a, l[p * 2] = T[p].b;
}
sort(T + 1, T + n + 1, cmp);
sort(l + 1, l + 2 * n + 1);
len = unique(l + 1, l + 2 * n + 1) - l;
bool vis = 0;
for(int p = 1; p <= n; p++) {
if(T[p].e) Union(G(T[p].a), G(T[p].b));
else if(Find(G(T[p].a)) == Find(G(T[p].b))) {
cout << "NO" << endl;
vis = 1;
break;
}
}
if(!vis) cout << "YES" << endl;
}
}