BZOJ 4236 JOIOJI - 玄学乱搞

推出个公式就成了大水题了,关键这个公式对于蒟蒻来说太难想了。
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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章