离散化 学习笔记

原文发布时间:2024-04-13 16:11。

离散化的作用

当一个数很大不能作为数组下标,但是数的个数很少时,就能使用离散化,省去中间的空间。

假如说有5个数11 100 1000 10000 1000000000000,虽然只有5个数却不能直接用数组存,不然会MLE,这时就可以离散化。

11->1
100->2
1000->3
10000->4
1000000000000->5

这时就只需要很小的数组就能存下了。

实现

map

使用

初始化

map<int, int> ls;//离散化数组,使用map,本质上是一个映射
int lst, sl[200005]; //lst记录当前下标,sl数组为ls的逆映射

存入

int in;//存入的数字in
cin >> in;
if (!ls.count(in)) {//判断ls中有没有存入的数字
	ls[in] = ++lst;//在ls中存入in离散化后的值
	sl[lst] = in;//在sl中存入ls的逆映射
}

调用

ls[in];//数字in离散化后的值
sl[in];//离散化后的值为in的数字

例题:P1955 [NOI2015] 程序自动分析

思路

离散化所有 i 和 j ,将所有 \(e=1\) 的 i 和 j 建并查集,然后判断 \(e=0\) 的 i 和 j 有没有在同一个集合中,如果有输出 NO ,否则输出 YES 。

注意

因为离散化要离散两个数 i 和 j ,所以 fa 数组和 sl 数组要开双倍空间,也就是 200005。因为题目是多测,所以要清空,也就是lst=0ls.clear()

代码

#include <bits/stdc++.h>

using namespace std;

#define int long long

map<int, int> ls;
int lst, sl[200005]; 
int a[200005], b[200005], c[200005];

int fa[200005];

int find(int x) {
	if (fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}

void q(int x, int y) {
	x = find(x);
	y = find(y);
	fa[x] = y;
	return ;
}

bool p(int x, int y) {
	x = find(x);
	y = find(y);
	if (x == y) return 1;
	return 0;
}

signed main() {
	int t;
	cin >> t;
	while (t--) {
		lst = 0;
		ls.clear();
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++) {
			cin >> a[i] >> b[i] >> c[i];
			if (!ls.count(a[i])) {
				ls[a[i]] = ++lst;
				sl[lst] = a[i];
			}
			if (!ls.count(b[i])) {
				ls[b[i]] = ++lst;
				sl[lst] = b[i];
			}
		} 
		for (int i = 1; i <= lst; i++) fa[i] = i;
		for (int i = 1; i <= n; i++) {
			if (c[i] == 1) q(ls[a[i]], ls[b[i]]);
		}
		bool ans = 1;
		for (int i = 1; i <= n; i++) {
			if (c[i] == 0) {
				if (p(ls[a[i]], ls[b[i]])) {
					ans = 0;
					break;
				}
			}
		}
		if (ans) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
 	return 0;
} 

hash

没有map好用,可以被map替代。

函数

例题:P3670 [USACO17OPEN] Bovine Genomics S

思路

枚举每个三元组(x,y,z),将A视为0,C视为1,G视为2,T视为3,对每个有斑点奶牛的三元组化四进制并存入数组cnt,然后对每个白奶牛的三元组化为四进制并在cnt中寻找有没有相同的,如果都没有则代表这是一个合法的三元组,ans++

代码

#include <bits/stdc++.h>

using namespace std;

#define int long long

int b[505][55], w[505][55];
int cnt[100];

signed main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			char in;
			cin >> in;
			if (in == 'A') b[i][j] = 0;
			if (in == 'C') b[i][j] = 1;
			if (in == 'G') b[i][j] = 2;
			if (in == 'T') b[i][j] = 3;
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			char in;
			cin >> in;
			if (in == 'A') w[i][j] = 0;
			if (in == 'C') w[i][j] = 1;
			if (in == 'G') w[i][j] = 2;
			if (in == 'T') w[i][j] = 3;
		}
	}
	int ans = 0;
	for (int x = 1; x <= m; x++) {
		for (int y = x + 1; y <= m; y++) {
			for (int z = y + 1; z <= m; z++) {
				bool f = 1;
				for (int i = 1; i <= n; i++) {
					int qwq = b[i][x] * 16 + b[i][y] * 4 + b[i][z];
					cnt[qwq]++;
				}
				for (int i = 1; i <= n; i++) {
					int qwq = w[i][x] * 16 + w[i][y] * 4 + w[i][z];
					if (cnt[qwq]) {
						f = 0;
						break;
					}
				}
				ans += f;
//				if (f) cout << x << ' ' << y << ' ' << z << endl;
				for (int i = 0; i < 100; i++) cnt[i] = 0;
			}
		}
	}
	cout << ans << endl;
	return 0;
} 
posted @ 2025-02-10 17:23  wwqwq  阅读(22)  评论(0)    收藏  举报