Codeforces 670C (离散化入门题)

原题链接:https://codeforces.com/problemset/problem/670/C

题目大意:

有 n 个人,每人会且仅会一种语言. (n ≤ 2e5)

语言有各自的编号(≤ 1e9)

这些人去看电影,一共有 m 种电影. (m ≤ 2e5)

每个电影的声音与字幕语言都不一样.

若有人的语言与声音语言一样,则称这个人很高兴♂.

若有人的语言与字幕语言一样,则称这个人比较高兴.

现让你选择一场电影,使得此电影中,很高兴的人最多,在此条件下,再使比较高兴的人最多.

分析:

因为要统计每种语言的人数,而语言编号 ≤ 1e9,存不下.

所以考虑离散化.

可得离散化之后,语言总数最多 n + 2m 种.

AC代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 2e5 + 5;
int n, m;
int a[maxn], b[maxn], c[maxn];
int sum[maxn * 3];
int cnt, mm;
int arr[maxn * 3], num[maxn * 3];
void discrete() {//离散化
    sort(arr + 1, arr + cnt + 1);
    for (int i = 1; i <= cnt; i++) {
        if (i == 1 || arr[i] != arr[i - 1])
            num[++mm] = arr[i];
    }
}
int query(int x) {//二分查找x的位置
    return lower_bound(num + 1, num + mm + 1, x) - num;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {//将所有电影和人涉及的语言放进一个数组,排序并离散化
        scanf("%d", &a[i]);
        arr[++cnt] = a[i];
    }
    scanf("%d", &m);
    for (int i = 1; i <= m; i++) {
        scanf("%d", &b[i]);
        arr[++cnt] = b[i];
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d", &c[i]);
        arr[++cnt] = c[i];
    }
    discrete();//离散化
    for (int i = 1; i <= n; i++) {
        int id = query(a[i]);//统计每种语言的人的数量
        ++sum[id];
    }
    int bmax = -1, cmax = -1, ans = 0;
    for (int i = 1; i <= m; i++) {//选择满足题目要求的电影
        int x = query(b[i]);
        int y = query(c[i]);
        if (sum[x] > bmax) {//优先考虑让很高兴的人最多
            bmax = sum[x], cmax = sum[y];
            ans = i;
        }
        else {
            if (sum[x] == bmax && sum[y] > cmax) {//如果答案不唯一、则在此前提下再让比较高兴的人最多
                bmax = sum[x], cmax = sum[y];
                ans = i;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

暴力解法:670ms

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int>PII;
int n, m;
int a[20000005];
map<int, int>mp;
int main() {
	//freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n;
	for (int i = 1, a; i <= n; ++i) 
		cin >> a, mp[a]++;
	int k, max1 = -1, max2 = -1;
	cin >> m;
	for (int i = 1; i <= m; ++i) {
		cin >> a[i];
		max1 = max(max1, mp[a[i]]);
	}
	for (int i = 1,b; i <= m; ++i) {
		cin >> b;
		if (mp[a[i]] == max1 && mp[b] > max2)
			max2 = mp[b], k = i;
	}
	cout << k << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces的动态规划单中,有基础DP、优化递推式、进阶DP、数据结构、优先队列、并查集、图论、最短路、最小生成树、数论、二分搜索等不同类型的目。 代码中的内容是一个动态规划的例子,它采用了一个二维数组来存储中间结果,并通过递推的方式计算最优解。这个例子中,它使用了一个for循环嵌套来遍历数组,并利用状态转移方程更新数组中的值。最后输出的是计算得到的最优解。 要注意的是,这段代码是一个完整的程序,需要依赖于一些特定的输入数据才能正确运行。如果你想在Codeforces上找到更多的动态规划目,可以访问它们的官方网站并浏览库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [牛客练习_21314:codeforces (动态规划+01背包)](https://blog.csdn.net/qq_45750296/article/details/109587967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [leetcode双人赛-acm-challenge-workbook:acm-挑战-工作簿](https://download.csdn.net/download/weixin_38701340/19923844)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round #750 (Div. 2)E(动态规划)](https://blog.csdn.net/m0_51506743/article/details/121083708)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值