题目
可能很多人要吐槽为什么标题不是“救救blabla”了。
怪人PM6喜欢数糖纸,不同的糖纸有不同的颜色,一共有 N 张糖纸,第 i 张糖纸颜色为 Ci ,它们的位置都是固定的。PM6喜欢五彩缤纷的糖纸,所以他不希望有重复的颜色。他有一次机会,可以收集任意一段连续区间内的糖纸。求出PM6最多能收集多少张糖纸。
输入描述
第一行一个正整数 N ,表示共有 N 张糖纸。
第二行共有 N 个正整数,第 i 个正整数表示第 i 张糖纸的颜色 Ci
对于20%的数据:1<=N<=100
对于40%的数据:1<=N<=1000
对于100%的数据:1<=N<=1e6,0<=Ci<=1e9
输出描述
一个整数表示PM6最多能收集多少张糖纸。
题目分析
1.桶排序的基础想法,可参考 本篇博客
2.题意可直观的理解为,遍历数组一次,找到其中数字不重复的最长区间,
但考虑到 0<=Ci<=1e9 ,如果开辟一个长度为1e9的数组作,似乎不太合理的,
可考虑将其进行离散化,来缩小需开辟数组的长度。
for (int i = 1;i <= n;i ++){
cin >> a[i];
b[i] = a[i];
}
sort(b + 1,b + n + 1);
int len = unique(b + 1,b + n + 1) - b - 1;
///离散化
for (int i = 1;i <= n;i ++){
//离散化后a[i]中存放的是,原a[i]的值在排序后b[i]中的位置
a[i] = lower_bound(b + 1, b + len + 1,a[i]) - b;
} 3.离散化后,从原来判断某个数是否重复出现,变为判断某个数排序后的位置是否重复出现,
这里通过一个 vis 数组来维护病判断是否重复出现。
4.AC代码
#include <bits/stdc++.h>
using namespace std;
#define long long LL
const int maxn = 1e6 + 5;
int a[maxn] , b[maxn];
int vis[maxn];
int n;
int main(){
while (~scanf("%d",&n)){
for (int i = 1;i <= n;i ++){
cin >> a[i];
b[i] = a[i];
}
sort(b + 1,b + n + 1);
int len = unique(b + 1,b + n + 1) - b - 1;
///离散化的目的:由于题目中给出的ci的值是1e9,开辟这么大的数组需要很大的空间
for (int i = 1;i <= n;i ++){
a[i] = lower_bound(b + 1, b + len + 1,a[i]) - b;///离散化
}
for (int i = 0;i <= len ;i ++) vis[i] = 0;
int l = 1,r = 1;
int ans = 0;
while (l <= r && r <= n){
while (!vis[a[r]] && r <= n){
vis[a[r]] = 1;
r ++;
}
ans = max(ans,r - l);
//这里需要注意,因为舒适重复的,获取区间长度后,需要将其遍历过的归零
while (vis[a[r]]){
vis[a[l ++]] = 0;
}
}
cout << ans << endl;
}
return 0;
}


京公网安备 11010502036488号