集合相似度(STL)

143 阅读2分钟

L2-005 集合相似度 (pintia.cn)

题目描述

给定两个整数集合,它们的相似度定义为:Nc/Nt×100Nc​/Nt​×100%。其中 NcNc​ 是两个集合都有的不相等整数的个数,NtNt​ 是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。

输入格式:

输入第一行给出一个正整数 N(50)N(≤50),是集合的个数。随后 NN 行,每行对应一个集合。每个集合首先给出一个正整数 M(104)M(≤10^4),是集合中元素的个数;然后跟 MM[0,109][0,10^9] 区间内的整数。

之后一行给出一个正整数 K(2000)K(≤2000),随后 KK 行,每行对应一对需要计算相似度的集合的编号(集合从 11NN 编号)。数字间以空格分隔。

输出格式:

对每一对需要计算的集合,在一行中输出它们的相似度,为保留小数点后 22 位的百分比数字。

输入样例:

3
3 99 87 101
4 87 101 5 87
7 99 101 18 5 135 18 99
2
1 2
1 3

输出样例:

50.00%
33.33%

题目分析

本题为 PTAl2 的一道题目,考察的是对 STL 工具的运用。

解如题意,即求两个集合各自的不同整数的数量,然后再求其交集数量为 NtNt,求其并集数量为 NcNc。最终用 printf 输出包含小数的答案。

一开始,我对每次枚举的两个集合使用 mapmap 求得答案,相关代码如下:

    map<int, bool> p1, p2;
    for (int i = 1; i <= cnt[x]; i ++)
        p1[a[x][i]] = true;
    int nc = 0, nt = p1.size();
    for (int i = 1; i <= cnt[y]; i ++)
    {
        if (p2[a[y][i]]) continue;
        if (p1[a[y][i]]) nc ++;
        else nt ++;
        p2[a[y][i]] = true;
    }

但对于最后一个测试点的反馈为 TLE

随后我尝试使用 mapmap 预处理每个集合的不重复数字集,随后却得到了错误答案,经过多次测试,发现在 if(p1[x][a[x][i]]) 后,当反馈为 falsefalse 时,p1[x].size() 会自加一,即当下次再用到当前 mapmap 时,初始化的 nt = p1.size() 会出错。

后来我尝试使用 setset 这个 STLSTL 进行储存,最终通过此题。

Accept代码

#include <bits/stdc++.h>

using namespace std;

const int N = 55, M = 1e4 + 10;
set<int> p[N];
int cnt[N];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int n; cin >> n;
    for (int i = 1; i <= n; i ++)
    {
        int s; cin >> s;
        for (int j = 0; j < s; j ++)
        {
            int x; cin >> x;
            p[i].insert(x);
        }
        cnt[i] = p[i].size();
    }
    int k; cin >> k;
    while (k --)
    {
        int x, y;
        cin >> x >> y;
        int nc = 0, nt = cnt[x];
        for (auto i : p[y])
        {
            if (p[x].count(i)) nc ++;
            else nt ++;
        }
        printf("%.2f%\n", (double)nc / nt * 100);
    }
    return 0;
}