传送门:
[1]:BZOJ
[2]:洛谷
•题解
定义数组 a,b,c 分别表示 'J' , 'O' , 'I' 的前缀和;
要想使区间 (L,R] 满足条件当且仅当 a[R]-a[L] = b[R]-b[L] = c[R]-c[L];
那么,由 a[R]-a[L] = b[R]-b[L] ⇔ a[R]-b[R] = a[L]-b[L];
同理,由 b[R]-b[L] = c[R]-c[L] ⇔ b[R]-c[R] = b[L]-c[L];
提前预处理出 a,b,c 数组后;
对于 i 位置,查找之前是否含有满足 ai-bi = aj-bj && bi-ci = bj-cj 的位置 j,并且 j 尽可能的小;
如何高效的查找呢?
使用 map<pair<int ,int > , int >;
对于之前处理过的位置 j ,将 aj-bj 和 bj-cj 存入到 pair<int ,int > 中,每次查找是否存在 (ai-bi,bi-ci) 即可;
如果存在,求解当前答案,反之,将其加入到map中;
•Code
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pii pair<int ,int > 4 const int maxn=2e5+50; 5 6 int n; 7 char s[maxn]; 8 int a[maxn]; 9 int b[maxn]; 10 int c[maxn]; 11 map<pii ,int >f; 12 13 int Solve() 14 { 15 f.clear(); 16 f[pii(0,0)]=0;///将(0,0)加入到f中 17 a[0]=b[0]=c[0]=0; 18 19 int len=strlen(s+1); 20 for(int i=1;i <= len;++i) 21 { 22 a[i]=a[i-1]+(s[i] == 'J'); 23 b[i]=b[i-1]+(s[i] == 'O'); 24 c[i]=c[i-1]+(s[i] == 'I'); 25 } 26 27 int ans=0; 28 for(int i=1;i <= len;++i) 29 { 30 pii tmp=pii(a[i]-b[i],b[i]-c[i]); 31 if(f.count(tmp)) 32 ans=max(ans,i-f[tmp]); 33 else 34 f[tmp]=i; 35 } 36 return ans; 37 } 38 int main() 39 { 40 scanf("%d",&n); 41 scanf("%s",s+1); 42 43 printf("%d ",Solve()); 44 45 return 0; 46 }