题目描述:
莫斯科正在举办一个大型国际会议,有n个来自不同国家的科学家参会。
每个科学家都只懂得一种语言。
为了方便起见,我们把世界上的所有语言用1到1e9之间的整数编号。
在会议结束后,所有的科学家决定一起去看场电影放松一下。
他们去的电影院里一共有m部电影正在上映,每部电影的语音和字幕都采用不同的语言。
对于观影的科学家来说,如果能听懂电影的语音,他就会很开心;如果能看懂字幕,他就会比较开心;如果全都不懂,他就会不开心。
现在科学家们决定大家看同一场电影。
请你帮忙选择一部电影,可以让观影很开心的人最多。
如果有多部电影满足条件,则在这些电影中挑选观影比较开心的人最多的那一部。
输入格式
第一行输入一个整数n,代表科学家的数量。
第二行输入n个整数a1,a2…an,其中ai表示第i个科学家懂得的语言的编号。
第三行输入一个整数m,代表电影的数量。
第四行输入m个整数b1,b2…bm,其中bi表示第i部电影的语音采用的语言的编号。
第五行输入m个整数c1,c2…cm,其中ci表示第i部电影的字幕采用的语言的编号。
请注意对于同一部电影来说,bi≠ci。
同一行内数字用空格隔开。
输出格式
输出一个整数,代表最终选择的电影的编号。
如果答案不唯一,输出任意一个均可。
数据范围
1≤n,m≤200000,
1≤ai,bi,ci≤1e9
输入样例:
3
2 3 2
2
3 2
2 3
输出样例:
2
难度:简单 |
时/空限制:1s / 64MB |
来源:《算法竞赛进阶指南》 |
分析:
如果不看语言编号的数据范围,本题最简单的方法是将语言编号作为下标索引,直接统计人数。但本题的语言编号的范围是1到1e9,显然需要这种办法需要过大的内存,即使语言种类实际数量要少得多。
另一种方法则是将编号按读入的顺序存入数组 temp,排序并去重,在数组 temp 的下标 i与数值 temp[i] 之间建立映射关系,这就是《算法竞赛进阶指南》中所说的离散化(即把整数集合Z的m个整数与1~m建立映射关系,使得一个时间,空间复杂度与数值范围Z的大小有关的算法降低为时间空间复杂度与m相关)。
于是我们可以建立一个数组num,用于统计每个语言对应科学家的数量,方法是通过遍历数组a,通过find函数找到 a[i] 在temp数组中的下标i,num[ find(a[i])]++,举个例子,假如语言编号5在temp数组的下标为2,那么语言编号5在num数组的下标也为2,于是每当我们遍历到的a[i]为5时,num[[2]]就加1。我们可以利用二分查找或者lower_bound函数查找下标。
但是需要注意的是b数组和c数组会出现a数组中没出现的语言编号,会使查找出现麻烦,所以我们把所有a,b,c数组的语言编号都放进temp数组进行排序去重。数组空间也要开三倍。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
int b;
int c;
int id;
}t[200005];
int a[200005];
int temp[600010];
int num[600005];
int k;
int find (int x){
int l = 0;
int r = k;
while(l < r){
int m = (l + r) >> 1;
if (x < temp[m])r = m;
else l = m + 1;
}
if (temp[l] == x)return l;
return l + 1;
}
bool cmp(node a, node b){
if (a.b != b.b)return a.b > b.b;
return a.c > b.c;
}
int main()
{
int n;
cin >> n;
int tot = 0;
for (int i = 0; i < n; i ++){
cin >> a[i];
temp[tot ++] = a[i];
}
int m;
cin >> m;
for (int i = 0; i < m; i ++ ){
cin >> t[i].b;
temp[tot ++] = t[i].b;
}
for (int i = 0; i < m; i ++){
cin >> t[i].c;
temp[tot ++] = t[i].c;
}
sort(temp, temp + tot);
k = unique(temp, temp + tot) - temp;
for (int i = 0; i < n; i ++)num[find(a[i])] ++;
for (int i = 0; i < m; i ++){
t[i].b = num[find(t[i].b)];
t[i].c = num[find(t[i].c)];
t[i].id = i;
}
sort(t, t + m, cmp);
cout << t[0].id + 1 << endl;
return 0;
}
这里find函数还可使用lower_bound函数
int find (int x){
return lower_bound(temp, temp + k, x) - temp;
}