#C231028B. 排列(per)
前言(Front talk)
网址(Website)
题目(Problem)
给定一个长度为
- 将当前
序列的最小值加入 序列末尾。 - 从
序列的开头或者末尾删去一个数。
小
对于
题解(Solution)
代码(Code)
#include<bits/stdc++.h>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
inline int input(){
char c;bool f=false;while(!isdigit(c=getchar()))f=c=='-';int x=c^48;
while(isdigit(c=getchar())){x=(((x<<2)+x)<<1)+(c^48);}return f?-x:x;
}
const int mod = 998244353;
const int N = 5005;
pair<int,int> mn[N][24];
int n,a[N];
int dp[N][N],sl[N][N],sr[N][N];
inline pair<int,int> ask(int l,int r){
int k=__lg(r-l+1);
return min(mn[l][k],mn[r-(1<<k)+1][k]);
}
inline void trans(int l,int r){
int minn=ask(l,r).second;
dp[l][r]=(1ll*sl[minn+1][r]+sr[l][minn-1]+1)%mod;
sl[l][r]=(1ll*sl[l][r-1]+dp[l][r])%mod;
sr[l][r]=(1ll*sr[l+1][r]+dp[l][r])%mod;
}
signed main(){
freopen("per.in","r",stdin);
freopen("per.out","w",stdout);
n=input();For(i,1,n) a[i]=input(),mn[i][0]={a[i],i};
for(int j=1;j<=18;j++)//预处理 ST 表
for(int i=1;i+(1<<j)-1<=n;i++)
mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
Rof(i,n,1) For(j,i,n) trans(i,j);
return printf("%lld",dp[1][n]),0;
}
后续(Ending)
__lg()
函数,不要用log2()
函数,否则时间会大量延长。(总时间延长