[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\n",ans); 28 return 0; 29 }