离散化 学习笔记
原文发布时间: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=0和ls.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;
}

浙公网安备 33010602011771号