题解 | #科学家的模型#

音乐家的曲调

https://ac.nowcoder.com/acm/contest/11175/B

B题

思路分析

题意:选三个互不相交的满足条件的区间,问这三个区间的长度之和最大是多少?
使用方法:尺取法(双指针)

思路如下:
不妨令三个区间为 左边的区间:A,中间的区间:B,右边的区间:C
令 res 为 三个区间的长度之和的最大值

我们枚举中间的区间:B         
假设B区间的范围为[l,r],则对于该区间而言 le[l-1] + r-l+1 + ri[r+1] 为res
ps :
le[i]: 区间[1,i] 内 满足条件的一个区间的最大长度
ri[i]: 区间[i,n] 内 满足条件的一个区间的最大长度

若共枚举到 num 个 B 区间,对于每一个 B 区间 我们会得到一个 res_i  // i的范围区间为 [1,num] 
则 最终的res = max(res_1,res_2,...,res_num) 

所以我们的思路是这样的:先求出 le[]数组 和 ri[] 数组 再 枚举B区间 求得 res

综上:Code 如下.

Code

#include <bits/stdc++.h>

using namespace std;

const int N=1e7+10;

int le[N],ri[N];
int cnt[26];  // 记录各个字母的出现次数
char s[N];
int n,m;

int main(){
    cin>>n>>m;
    cin>>s+1;

    // 求 le数组
    for(int i=1,j=1;j<=n;j++){
        cnt[s[j]-'a']++;
        while(cnt[s[j]-'a']>m&&i<=j) cnt[s[i]-'a']--,i++;
        le[j]=max(le[j-1],j-i+1);
    }

    // 求 ri数组
    memset(cnt,0,sizeof cnt);
    for(int i=n,j=n;i>=1;i--){
        cnt[s[i]-'a']++;
        while(cnt[s[i]-'a']>m&&i<=j) cnt[s[j]-'a']--,j--;
        ri[i]=max(ri[i+1],j-i+1);
    }

    // 枚举B区间 得到res 
     int res=-1;
     memset(cnt,0,sizeof cnt);
     for(int i=1,j=1;j<=n;j++){
        cnt[s[j]-'a']++;
        while(cnt[s[j]-'a']>m&&i<=j) cnt[s[i]-'a']--,i++;
        res=max(res,le[i-1]+j-i+1+ri[j+1]);
    }

    cout<<res<<endl;

    return 0;
}
全部评论
可以优化一下,求 le 数组统合到枚举B区间中,我是萌新,微博的见解!
点赞 回复 分享
发布于 2021-07-04 11:50

相关推荐

找不到工作死了算了:没事的,雨英,hr肯主动告知结果已经超越大部分hr了
点赞 评论 收藏
分享
10-11 17:45
门头沟学院 Java
走吗:别怕 我以前也是这么认为 虽然一面就挂 但是颇有收获!
点赞 评论 收藏
分享
评论
6
收藏
分享
牛客网
牛客企业服务