(虽然是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); }