离散化

P1955 程序自动分析

如果不知道这道题的,可以先看看我那篇并查集的博客,里面有对这道题的主要思想的讲解,那么这里主要是讲其中的没有实现的部分——离散化

但是这里还是只讲一些基础的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;
}
posted @ 2020-06-18 16:16  Poetic_Rain  阅读(89)  评论(1编辑  收藏  举报