bzoj3521: [Poi2014]Salad Bar

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3521: [Poi2014]Salad Bar相关的知识,希望对你有一定的参考价值。

Description

有一个长度为n的字符串,每一位只会是p或j。你需要取出一个子串S(从左到右或从右到左一个一个取出),使得不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数。你需要最大化|S|。

Input

第一行一个数n,第二行一个长度n的字符串。

Output

S的最大长度。

单调栈预处理出每个左端点向右延伸的最右位置和每个右端点向左延伸的最左位置,然后随便用数据结构维护一下就行了

#include<cstdio>
int n,v[1000007],l[1000007],r[1000007],ss[1000007],sp=0,ans=0;
char s[1000007];
int mx[1000007],es[1000007],enx[1000007],e0[1000007],ep=2;
int tr[2097152];
void maxs(int&a,int b){if(a<b)a=b;}
int main(){
    scanf("%d%s",&n,s+1);
    for(int i=1;i<=n;++i)v[i]=v[i-1]+(s[i]==p?1:-1);
    for(int i=0;i<=n;++i){
        while(sp&&v[ss[sp]]>v[i])r[ss[sp--]]=i-1;
        ss[++sp]=i;
    }
    while(sp)r[ss[sp--]]=n;
    for(int i=n;i;--i){
        while(sp&&v[ss[sp]]<v[i])l[ss[sp--]]=i+1;
        ss[++sp]=i;
    }
    while(sp)l[ss[sp--]]=0;
    for(int i=0;i<=n;++i){
        es[ep]=i;enx[ep]=e0[l[i]];e0[l[i]]=ep++;
    }
    for(int i=0;i<=n;++i){
        for(int e=e0[i];e;e=enx[e]){
            int u=es[e];
            for(int w=u+1048577;w;w>>=1)maxs(tr[w],u);
        }
        int v=0;
        for(int l=i+1048576,r=::r[i]+1048578;l^r^1;l>>=1,r>>=1){
            if(~l&1)maxs(v,tr[l^1]);
            if(r&1)maxs(v,tr[r^1]);
        }
        maxs(ans,v-i);
    }
    printf("%d",ans);
    return 0;
}

 

以上是关于bzoj3521: [Poi2014]Salad Bar的主要内容,如果未能解决你的问题,请参考以下文章

LuoguP3521 [POI2011]ROT-Tree Rotations

P3521 [POI2011]ROT-Tree Rotations

P3521 [POI2011]ROT-Tree Rotations

Luogu P3521 [POI2011]ROT-Tree Rotations

题解 P3521 [POI2011]ROT-Tree Rotations

「Luogu P3521 [POI2011]ROT-Tree Rotations」