Atcoder Beginner Contest 210
C - Colorful Candies:
题目:
C - Colorful Candies
Time Limit: 2 sec / Memory Limit: 1024 MB
Score : 300points
Problem Statement
There are N candies arranged in a row from left to right.
Each of these candies has one color that is one of the 10^9 colors called Color 1, Color 2, ……, and Color 10^9.
For each i=1,2,…,N the color of the i-th candy from the left is Color ci.
From this row, Takahashi can choose K consecutive candies and get them.
That is, he can choose an integer i such that 1 ≤ i ≤ N−K+1 and get the i-th, (i+1)-th, (i+2)-th, ……, (i+K−1)-th candy from the left. Takahashi likes to eat colorful candies, so the more variety of colors his candies have, the happier he will be.
Print the maximum possible number of distinct colors in candies he gets. Constraints 1 ≤ K ≤ N ≤3×10^5 , 1≤ ci ≤10^9
All values in input are integers.
输入输出:
lnput
Input is given from Standard Input in the following format:
N K
c1 c2 c3 … cN
Output
Print the maximum possible number of distinct colors in candies Takahashi gets.
Simple input 1:
10 6
304621362 506696497 304621362 506696497 834022578 304621362 414720753 304621362 304621362 414720753
output:4
Simpe input 2:
5 5
4 4 4 4 4
output :1
C++ 代码:
思路:
注意到本题糖果数量N只有3 *10^5 个,但是用来表示糖果颜色ci的数据范围却是10^9,所以如果开一个10的9次方的数组来存取糖果的颜色是显然不合理的,对于这种情况,我是采用离散化的方式来实现用大小为3 * 10^5的数组来存取ci。
此外,为了防止超时的问题,我们不能直接来一个三重循环调用,要将问题分解,可以发现对于N个ci, 我们可以每次取出K个数据来分析,循环遍历,而下一组K个数据比较前一组的差别只在于ci 和 c(i-k), 发现这个规律,我们可以只遍历一遍数组就能得到答案。
具体过程看代码:
#include<iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> alls;
// 二分求出x对应的离散化的值
int find(int x) // 找到第一个大于等于x的位置
{
int l = 0, r = alls.size() - 1;
while (l < r)
{
int mid = l + r >> 1;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r+1 ; // 映射到 1, 2, ...n
}
int a[300010];
int b[300010]={0};
int main(){
int n,k,x;
cin >> n >> k;
for(int i=1;i<=n;i++){
cin >> x;
a[i]=x;
alls.push_back(x);
}
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
int cnt=0;
int max=0;
for(int i=1; i<=k; i++){
if(b[find(a[i])] == 0) cnt++;
b[find(a[i])]++;
}
max = cnt;
for(int i=k+1; i<=n; i++){
b[find(a[i-k])]--;
if(b[find(a[i-k])] == 0) cnt--;
if(b[find(a[i])] == 0) cnt++;
b[find(a[i])]++;
if(cnt > max) max = cnt;
if(max == k){
cout << k;
return 0;
}
}
cout << max;
return 0;
}
AND
附上官方的题解
采用map的方法来解决,更简单明了
#include <iostream>
#include <map>
using namespace std;
int n, k;
int c[300005];
map<int, int> mp;
int main(void)
{
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> c[i];
for(int i = 1; i <= k; i++) mp[c[i]]++;
int ans = mp.size();
for(int i = k+1; i <= n; i++){
mp[c[i]]++;
mp[c[i-k]]--;
if(mp[c[i-k]] == 0) mp.erase(c[i-k]);
ans = max(ans, (int)mp.size());
}
cout << ans << endl;
return 0;
}
map 的基本操作函数:
C++ Maps 是一种关联式容器,包含“关键字/值”对:
基本操作:
begin() ———— 返回指向 map 头部的迭代器
erase() ————删除一个元素
max_size() ———— 返回可以容纳的最大元素个数
find() ———— 查找一个元素
map提供的是一种键值对容器,里面的数据都是成对出现,在解题的时候非常好用。