[BZOJ4236]JOIOJI

设a[i],b[i],c[i]分别为前i个数中J,O,I的个数,则一个区间[L+1,R]合法当且进当:

a[r]-a[l]=b[r]-b[l]=c[r]-c[l]。

即a[l]-b[l]=a[r]-b[r],a[l]-c[l]=a[r]-c[r],b[l]-c[l]=b[r]-c[r]。

用map记录每个三元组<a[i],b[i],c[i]>第一次出现的位置,每次尝试更新答案。

 1 #include<map>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6 
 7 const int N=200010;
 8 int n,ans,sm1[N],sm2[N],sm3[N];
 9 char s[N];
10 struct P{ int a,b,c; };
11 bool operator <(const P &a,const P &b)
12 { return (a.a==b.a) ? (a.b==b.b ? a.c<b.c : a.b<b.b) : a.a<b.a; }
13 map<P,int>mp;
14 
15 int main(){
16     freopen("bzoj4236.in","r",stdin);
17     freopen("bzoj4236.out","w",stdout);
18     scanf("%d%s",&n,s+1); mp[(P){0,0,0}]=0;
19     rep(i,1,n){
20         sm1[i]=sm1[i-1]; sm2[i]=sm2[i-1]; sm3[i]=sm3[i-1];
21         if (s[i]=='J') sm1[i]++;
22         if (s[i]=='O') sm2[i]++;
23         if (s[i]=='I') sm3[i]++;
24         P t=(P){sm1[i]-sm2[i],sm1[i]-sm3[i],sm2[i]-sm3[i]};
25         if (mp.count(t)) ans=max(ans,i-mp[t]); else mp[t]=i;
26     }
27     printf("%d
",ans);
28     return 0;
29 }
原文地址:https://www.cnblogs.com/HocRiser/p/9894032.html