BZOJ 4236 JOIOJI

来源:互联网 发布:xy苹果助手for mac 编辑:程序博客网 时间:2024/05/16 11:57

推出个公式就成了大水题了,关键这个公式对于蒟蒻来说太难想了。
sum为前缀中各个字母个数,假设一段区间[j,i]满足条件,则有:

sumO[i]sumO[j1]=sumI[i]sumI[j1]=sumJ[i]sumJ[j1]

等价于:
{sumO[i]sumI[i]=sumO[j1]sumI[j1]sumO[i]sumJ[i]=sumO[j1]sumJ[j1]

看到这个,有一点像斜率优化整理时的思想,将关于当前状态的放在一侧,之前状态的放在另一侧,于是维护一下第一次出现二元组相等的最小时间就好了。

#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;} 
原创粉丝点击