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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章