NEFU OJ 2118 相似的数集高级版-set

Problem:2118
Time Limit:3000ms
Memory Limit:665535K

Description

给出两个数集,它们的相似程度定义为Nc/Nt*100%。其中,Nc表示两个数集中相等的、两两互不相同的元素个数,而Nt表示两个数集中总共的互不相同的元素个数。请计算任意两个给出数集的相似程度。

Input

输入第一行给出一个正整数N(N<=50),是集合的个数。随后N行,每行对应一个集合。每个集合首先给出一个正整数M(M<=10^4),是集合中元素的个数;然后跟M个[0, 10^9]区间内的整数。
之后一行给出一个正整数K(K<=2000),随后K行,每行对应一对需要计算相似度的集合的编号(集合从1到N编号)。数字间以空格分隔。

Output

输出共K行,每行一个保留2位小数的实数,表示给定两个集合的相似度值。

Sample Input

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

Sample Output

50.00% 
33.33%

Source

信息学奥赛课课通


Tips

很容易超时,在疯狂的优化下终于 AC 了。
最开始编译器卡了一下,我以为 set 数组很慢,不能用 set 数组,然后就改成数组排序去重了,结果差不多,正常应该是怎么解都行。

蒟蒻的一些思路:
首先,把所有集合读入数组,读完立刻去重,采用 sort+unique 方式。
然后依次读取要比较的两个集合,由于之前已经排好序了,所以只需要按顺序比较找出两数组中相同元素个数即可。
注:使用 unique 前需要先进行排序。

Code

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int arr[50][10001]; //存储集合中各个元素,多的最后一位存集合中元素个数
	double ans[50][50]={0},r; //ans记录之前的查询
	int n,num,s1,s2,same,tmp,sp1,sp2;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&arr[i][10000]);
		for(int j=0;j<arr[i][10000];j++)
		{
			scanf("%d",&arr[i][j]);
		}
		sort(arr[i],arr[i]+arr[i][10000]); //排序
		arr[i][10000]=unique(arr[i],arr[i]+arr[i][10000])-arr[i]; //去重
	}
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d %d",&s1,&s2);
		if(ans[s1-1][s2-1]!=0) //已经计算过直接输出
		{
			printf("%.2f%\n",ans[s1-1][s2-1]);
			continue;
		}
		same=0;
		sp1=sp2=0;
		while(sp1<arr[s1-1][10000]&&sp2<arr[s2-1][10000]) //比较获取相同元素个数
		{
			//小的元素指针+1,元素相等same+1
			if(arr[s1-1][sp1]<arr[s2-1][sp2])sp1++;
			else if(arr[s1-1][sp1]>arr[s2-1][sp2])sp2++;
			else
			{
				same++;
				sp1++;
				sp2++;
			}
		}
		r=same*100.0/(arr[s1-1][10000]+arr[s2-1][10000]-same); //计算答案
		ans[s1-1][s2-1]=ans[s2-1][s1-1]=r; //存储答案
		printf("%.2f%\n",r);
	}
	return 0;
}
发布了64 篇原创文章 · 获赞 206 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/csg999/article/details/104381074