离散化 AcWing103.电影 + 用map做

https://www.acwing.com/problem/content/105/

莫斯科正在举办一个大型国际会议,有n个来自不同国家的科学家参会。

每个科学家都只懂得一种语言。

为了方便起见,我们把世界上的所有语言用110^9之间的整数编号。

在会议结束后,所有的科学家决定一起去看场电影放松一下。

他们去的电影院里一共有m部电影正在上映,每部电影的语音和字幕都采用不同的语言。

对于观影的科学家来说,如果能听懂电影的语音,他就会很开心;如果能看懂字幕,他就会比较开心;如果全都不懂,他就会不开心。

现在科学家们决定大家看同一场电影。

请你帮忙选择一部电影,可以让观影很开心的人最多。

如果有多部电影满足条件,则在这些电影中挑选观影比较开心的人最多的那一部。

输入格式

第一行输入一个整数n,代表科学家的数量。

第二行输入n个整数a1,a2an,其中ai表示第i个科学家懂得的语言的编号。

第三行输入一个整数m,代表电影的数量。

第四行输入m个整数b1,b2bm,其中bi表示第i部电影的语音采用的语言的编号。

第五行输入m个整数c1,c2cm,其中ci表示第i部电影的字幕采用的语言的编号。

请注意对于同一部电影来说,bici。

同一行内数字用空格隔开。

输出格式

输出一个整数,代表最终选择的电影的编号。

如果答案不唯一,输出任意一个均可。

数据范围

1n,m200000,
1ai,bi,ci10^9

输入样例:

3
2 3 2
2
3 2
2 3

输出样例:

2

 

 

我们只需要计算出懂某种语言的人的数量有多少,然后枚举每个电影就能找出最好的电影。

然而语言的范围有1e9,超过了允许的储存空间,但是语言的种类不会超过n<=2e5种,所以我们可以使用离散化的技巧。

离散化:

(《算法竞赛进阶指南》)

 

 

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=2e5+5;
 9 
10 int a[N],b[N],c[N];
11 int d[N];
12 int know[N];
13 int n,m,cnt=0;
14 
15 void discrete() {
16     sort(a+1,a+n+1);
17     for(int i=1;i<=n;i++) {
18         if(i==1||a[i]!=a[i-1]) {
19             d[++cnt]=a[i];
20         }
21     }
22 }
23 
24 int query(int x) {
25     int find=lower_bound(d+1,d+cnt+1,x)-d;
26     if(d[find]!=x) return 0;
27     return find;
28 }
29 
30 int main() {
31     scanf("%d",&n);
32     for(int i=1;i<=n;i++) {
33         scanf("%d",&a[i]);
34     }
35     scanf("%d",&m);
36     for(int i=1;i<=m;i++) {
37         scanf("%d",&b[i]);
38     }
39     for(int i=1;i<=m;i++) {
40         scanf("%d",&c[i]);
41     }
42     discrete();
43     for(int i=1;i<=n;i++) {
44         know[query(a[i])]++;
45     }
46     int MAX1=-1,MAX2=-1,maxn;
47     for(int i=1;i<=m;i++) {
48         int x=query(b[i]),y=query(c[i]);
49         if(MAX1<know[x]||(MAX1==know[x]&&MAX2<know[y])) {
50             MAX1=know[x];
51             MAX2=know[y];
52             maxn=i;
53         }
54     }
55     printf("%d\n",maxn);
56     return 0;
57 }

 

离散化可以压缩空间复杂度,同时也保留了数据之间的大小关系,但我们可以发现这题对元素之间的大小关系并没有要求,所以可以用另外的方法比如用map来做,这种方法的好处在于增加或删除元素十分方便,只需O(logN)的时间复杂度,而如果用离散化的话只能重新排序或者从中间插入元素,时间复杂度为O(N*logN),所以这种方法十分有价值。

代码:(这题对常数的要求较高,提交这段代码会TLE,不过时间复杂度是一样的,没啥毛病)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <map> 
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 const int N=2e5+5;
10 
11 map <int,int> discrete;
12 
13 int a[N],b[N],c[N];
14 int know[N];
15 int n,m,cnt=0;
16 
17 int main() {
18     scanf("%d",&n);
19     for(int i=1;i<=n;i++) {
20         scanf("%d",&a[i]);
21         int tmp=discrete[a[i]];
22         if(!tmp) {
23             discrete[a[i]]=++cnt;
24             know[cnt]++;
25         }else {
26             know[tmp]++;
27         }
28     }
29     scanf("%d",&m);
30     for(int i=1;i<=m;i++) {
31         scanf("%d",&b[i]);
32     }
33     for(int i=1;i<=m;i++) {
34         scanf("%d",&c[i]);
35     }
36     int MAX1=-1,MAX2=-1,maxn;
37     for(int i=1;i<=m;i++) {
38         int x=discrete[b[i]],y=discrete[c[i]];
39         if(MAX1<know[x]||(MAX1==know[x]&&MAX2<know[y])) {
40             MAX1=know[x];
41             MAX2=know[y];
42             maxn=i;
43         }
44     }
45     printf("%d\n",maxn);
46     return 0;
47 }

 

posted @ 2020-03-15 18:10  俩小圈  阅读(243)  评论(0)    收藏  举报