离散化
如果不知道这道题的,可以先看看我那篇并查集的博客,里面有对这道题的主要思想的讲解,那么这里主要是讲其中的没有实现的部分——离散化
但是这里还是只讲一些基础的STL的直接莽的方法,因为哈希表离散化我不会啊,离散化是个什么东西呢???
离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。
以上摘自百度百科
可能有点不太明白,大概就是,在我们处理一道题的时候,面对数据非常得大,我们直接用数组下标来存储它肯定是要爆的,但其实它的数据个数不太多,我们就可以将这个超级大的数据换一个东西来表示它(是不是有点感觉了),如下:
原数组:
32165451,6565164616,321
排序后:
6565164616,32165451,321
离散化后:
1,2,3
比如说以上的例子,我们就可以用排名来代替原来的数据,就可以用数组下标存储了。那么对于以上的操作,可以直接用STL的函数一笔带过,具体实现以这道题为例
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+10;
struct node{
int x,y,e;
}a[MAXN];
int b[MAXN],i,t,n,tot,res;
bool ok=false;
int f[MAXN];
int find(int x){
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
void merge(int x,int y){
f[find(x)]=find(y);
}
bool cmp(node q,node w){
return q.e>w.e;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(f,0,sizeof f);
tot=0;
for(i=1;i<=n;i++){
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].e);
b[++tot]=a[i].x;
b[++tot]=a[i].y;
} //b是用来离散化的一个副本,tot表示元素个数,将a的值丢进去
sort(b+1,b+1+tot); //对所有元素进行排序
res=unique(b+1,b+1+tot)-b-1; //unique去重函数,它返回的是尾地址,减去首地址之后就是剩下的元素个数
for(i=1;i<=n;i++){
a[i].x=lower_bound(b+1,b+1+res,a[i].x)-b; //lower_bound是自带的二分查找函数,在数组中查找大于等于a[i].x的最小整数的下标
a[i].y=lower_bound(b+1,b+1+res,a[i].y)-b; //将找到的下标存进原来的数组中,就将大数据转换为排名了,整个离散化结束
}
for(i=1;i<=res;i++) f[i]=i; //以元素个数来赋初值
ok=false;
sort(a+1,a+1+n,cmp);
for(i=1;i<=n;i++){
if(a[i].e==1){
merge(a[i].x,a[i].y);
}else{
if(find(a[i].x)==find(a[i].y)){
ok=true;
break;
}
}
}
if(ok==true) puts("NO");
else puts("YES");
}
return 0;
}