题解 | #科学家的模型#
音乐家的曲调
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; }