2018多校集训 H. Hills And Valleys
传送门
题意
给你一个n≤105的序列,数字都是0-9,你可以任意翻转一个子区间,问翻转后最长不降子序列的最大长度。
题解
简略题解:我开始考虑的是fi,j,k表示的是翻转i结尾的区间,翻转区间贡献了最长不降序列中j到k的部分, 那么只要新加入的数小于j就可以翻过去,大于k就可以补到后面,但其实有问题,因为你不知道翻转区间之前的区间贡献的范围,所以要记录fi,j,k,l多一个状态表示翻转区间之前贡献了1−l,但这样会爆炸空间,我不知道能不能滚动数组,我最后考虑使用性质优化:对于一个翻转区间, 如果区间端点不是贡献最小值,或者贡献最大值,也就是端点不参与贡献,那么翻转一个更小不包括端点的区间必然更优。所以我们考虑直接使得右端点是最大值,那么就可以少存一位,然后枚举上一个最大值就好了,对于每一个最大值,只枚举最近的一个数就好了。
实现
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
int read(){
int num=0, flag=1; char c=getchar();
while(!isdigit(c) && c!='-') c=getchar();
if(c == '-') flag=-1, c=getchar();
while(isdigit(c)) num=num*10+c-'0', c=getchar();
return num*flag;
}
int readc(){
char c=getchar();
while(!isdigit(c)) c=getchar();
return c-'0';
}
const int N = 1e5+1000;
const int M = 10;
int n, T;
int a[N];
int f[N][M][M], L[N][M][M];
int g[N][M];
int h[N][M];
int las[N][M];
int main(){
T = read();
while(T--){
n = read();
for(int i=1; i<=n; i++) a[i]=readc();
for(int i=1; i<=n; i++){
for(int j=0; j<M; j++) las[i][j] = las[i-1][j];
if(i != 1) las[i][a[i-1]] = i-1;
}
for(int i=0; i<=n+1; i++){
for(int j=0; j<M; j++){
g[i][j] = 0;
h[i][j] = 0;
for(int k=0; k<M; k++){
f[i][j][k] = 0;
}
}
}
for(int i=1; i<=n; i++){
for(int j=0; j<M; j++){
g[i][j] = g[i-1][j];
if(a[i] <= j) g[i][j] = max(g[i][j], g[i-1][a[i]] + 1);
}
}
for(int i=1; i<=n; i++){
for(int j=0; j<M; j++){
for(int k=j; k<M; k++){
f[i][j][k]=0,L[i][j][k]=i;
if(a[i]<=k && a[i]>=j) {
f[i][j][k]=g[i-1][j]+1;
for(int l=k; l>=a[i]; l--){
int nex = las[i][l];
int res=f[nex][j][k]+1;
if(res>f[i][j][k]) f[i][j][k]=res, L[i][j][k]=L[nex][j][k];
}
}
}
}
}
for(int i=n; i>=1; i--){
for(int j=0; j<M; j++){
h[i][j] = h[i+1][j];
if(a[i] >= j){
h[i][j] = max(h[i][j], h[i+1][a[i]]+1);
}
}
}
int ans=0, ansl=1, ansr=1;
for(int i=1; i<=n; i++){
for(int j=0; j<M; j++){
for(int k=j; k<M; k++){
if(f[i][j][k] + h[i+1][k] > ans){
ans=f[i][j][k] + h[i+1][k], ansl=L[i][j][k], ansr=i;
}
}
}
}
printf("%d %d %d\n", ans, max(1, ansl), ansr);
// printf("%d\n", ans);
}
return 0;
}
/*
1
9
203258468
*/
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 历时半年,我将一个大型asp.net的零代码快速开发平台转成了java
· C#实现语音预处理:降噪、静音检测、自动增益(附Demo源码)
· 记一次 .NET 某无语的电商采集系统 CPU爆高分析
· Spring Boot 启动优化实践
· Coze工作流实战:一键生成治愈风格视频