Codechef August Challenge 2018 : Safe Partition

传送门

(虽然是A了但是不知道复杂度是不是正确的

考虑以某个位置为结尾的合法划分

先考虑min,带来的影响是限制了最小长度,预处理出这个最小长度后,这可以在处理到这个数时,把不能算的部分去掉(不满足min条件的话必定满足max条件)。

单独考虑max条件

对于每一个数,找出以它为最大值的区间后,暂时不考虑min,就只限制了划分的最大长度,这时分类讨论一下(见代码),有一部分需要暴力处理(不会证复杂度)

#include<cstdio>
#include<algorithm>
#define MN 510000
using namespace std;

const int MOD=1e9+7;
int n,m,a[MN],_l[MN],st[MN],top=0,v[MN],V[MN],tmp,ans,fi[MN],ne[MN];
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
inline void M(int &x){while(x>=MOD)x-=MOD;while(x<0)x+=MOD;}
inline int ask(int l,int r){int a=V[r-1]-(l==1?0:V[l-2]);M(a);return a;}
inline void add(int l,int r,int sum){M(v[l]+=sum);M(v[r+1]-=sum);}
inline void work(int s,int _s,int l){
    int sum=0;
    for (int i=1;i<=l;i++){
        add(_s,_s+i-1,ask(s+i-1,s+i-1));
    }
}
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    
    int L=1,R=0;
    for (int i=1;i<=n;i++){
        while(L<=R&&a[st[R]]>=a[i]) R--;
        st[++R]=i;
        while(L<R&&i-a[st[L+1]]+1>=st[L]) L++;
        _l[i]=max(min(st[L],i-a[st[L]]+1),0);
    }
    
    V[0]=1;
    for (int i=1;i<=n;i++){
        while(a[st[top]]<=a[i]&&top) ne[st[top]]=i,top--;fi[i]=st[top];
        st[++top]=i;
    }
    for (int i=1;i<=n;i++){
        int l=fi[i]+1,r=ne[i]?ne[i]-1:n,sum;
        if (a[i]>=r-l+1){
            add(i,r,ask(l,i));
        }else if (a[i]>=i-l+1&&a[i]>=r-i+1){
            add(i,l+a[i]-1,ask(l,i));
            add(l+a[i],r,ask(r-a[i]+1,i));
            work(l+1,l+a[i],r-(l+a[i]));
        }else if (a[i]<=i-l+1&&a[i]<=r-i+1){
            work(i-a[i]+1,i,a[i]);
        }else if (a[i]<=i-l+1){
            add(i,r,ask(r-a[i]+1,i));
            work(i-a[i]+1,i,r-i);
        }else if (a[i]<=r-i+1){
            add(i,l+a[i]-1,ask(l,i));
            work(l+1,l+a[i],i-l);
        }
        M(tmp+=v[i]);
        M(ans=tmp-ask(_l[i]+1,i));
        M(V[i]=ans+V[i-1]);
    }
    printf("%d
",ans);
}
View Code
原文地址:https://www.cnblogs.com/Enceladus/p/9494066.html