推出個公式就成了大水題了,關鍵這個公式對於蒟蒻來說太難想了。
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;
}