推出个公式就成了大水题了,关键这个公式对于蒟蒻来说太难想了。
sum为前缀中各个字母个数,假设一段区间[j,i]满足条件,则有:
sumO[i]−sumO[j−1]=sumI[i]−sumI[j−1]=sumJ[i]−sumJ[j−1]
等价于:
{sumO[i]−sumI[i]=sumO[j−1]−sumI[j−1]sumO[i]−sumJ[i]=sumO[j−1]−sumJ[j−1]
看到这个,有一点像斜率优化整理时的思想,将关于当前状态的放在一侧,之前状态的放在另一侧,于是维护一下第一次出现二元组相等的最小时间就好了。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=200005;
struct node
{
int pos,x,y;
bool operator == (const node &tmp)const
{
return x==tmp.x&&y==tmp.y;
}
bool operator < (const node &tmp)const
{
return x<tmp.x||(x==tmp.x&&y<tmp.y)||(x==tmp.x&&y==tmp.y&&pos<tmp.pos);
}
};
int n,ans;
int sumi[maxn],sumj[maxn],sumo[maxn];
set<node>q;
int main()
{
scanf("%d\n",&n);
for(int i=1,ch;i<=n;i++)
{
ch=getchar();
sumj[i]=sumj[i-1];
sumo[i]=sumo[i-1];
sumi[i]=sumi[i-1];
if(ch=='J')sumj[i]++;
else if(ch=='O')sumo[i]++;
else sumi[i]++;
}
set<node>::iterator it;
q.insert((node){0,0,0});
for(int i=1;i<=n;i++)
{
node now=(node){0,sumj[i]-sumo[i],sumo[i]-sumi[i]};
it=q.lower_bound(now);
if(*it==now)ans=max(ans,i-(*it).pos);
now.pos=i;
q.insert(now);
}
cout<<ans;
return 0;
}