链接:https://ac.nowcoder.com/acm/problem/20863
来源:牛客网
题目描述
可能很多人要吐槽为什么标题不是“救救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最多能收集多少张糖纸。
输入
5
1 2 2 3 4
输出
3
说明
PM6可以收集第3到第5张的糖纸,共有三张。
解题时想法:
看到连续区间就头又大了,但其实不难。
第一种解法
unordered_set<int>b;
unordered_map<int,int>c;
int main(){
read(n);
for(int i=0;i<n;i++){
read(a[i]);
}
int l=0,r=0;
while(l<n){
while(r<n&&b.count(a[r])==0){
b.insert(a[r]);
c[a[r]]++;
r++;
}
cnt=b.size();
ans=max(ans,cnt);
if(c[a[l]]==1){
c[a[l]]=0;
b.erase(a[l]);
}else{
c[a[l]]--;
}
l++;
}
cout<<ans<<endl;
return 0;
}
思路:
l,r卡区间;
while循环 r++ 如果碰到重复值了就跳出,取unordered_set的size更新ans;
每次循环判断 如果a[l]只出现了一次,就从unordered_set里清除,
这样的复杂度应该是O(2n)
刷了3次才卡评测机过了。。。
第二种解法:
read(n);
for(int i=0;i<n;i++){
read(a[i]);
}
int l=0,r=0;
while(r<n){
if(b[a[r]%mod]==0){
ans=max(ans,r-l+1);
}else{
while(b[a[r]%mod]){
b[a[l++]%mod]=0;
}
}
b[a[r++]%mod]=1;
}
cout<<ans<<endl;
思路:
每次判断a[r]是否重复,
未重复则直接加;
重复则while循环将a[l]记为0,l++;(例 1,2,3,4,4),这样就定位到重复的那个位上了(因为区间里不允许有重复存在)
这个解法用了手写哈希,设的mod是1e6+7。
复杂度好像也是O(2n)??
但是为什么直接100ms就过了呢
额 这个问题先留着(是因为用了set?)