【动态规划】【动态 DP】 CF750E New Year and Old Subsequence
题目描述
定义数字串是好的当且仅当其包含子序列 2017 ,不包含子序列 2016。
定义数字串的丑陋值为最少删掉几个字符,它才能是好的,如果一直不能,就是
给定数字串
算法描述
对于这种问题,我们先探究如果给你一个数字串,怎样求丑陋值。
我们发现由于是子序列,情况太复杂,没办法讨论,考虑 dp。每个点的状态定义为在其之前凑出关键字串的 “进度”,
注意这里的
这样可以
那么怎样回答区间呢?
考虑用 DDP 的思路转化成矩阵,再套上线段树。这里采用
线段树上每个点初始化,区间询问将其乘起来,再左乘上初始矩阵
时间复杂度
这题可以说是最简单的 DDP 转化,由此看出如果涉及修改的话直接单点改某一个矩阵即可,复杂度
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5,inf = 0x3f3f3f3f;
struct Matrix{
int a[5][5];
};
Matrix operator *(Matrix x,Matrix y)
{
Matrix z;
for(int i = 0;i < 5;i++)
for(int j = 0;j < 5;j++)
{
z.a[i][j] = inf;
for(int k = 0;k < 5;k++)
z.a[i][j] = min(z.a[i][j],x.a[i][k] + y.a[k][j]);
}
return z;
}
int n,q;
char s[N];
struct Segment_Tree{
Matrix a[N << 2];
inline void pushup(int pos) {a[pos] = a[pos << 1] * a[pos << 1 | 1];}
inline void build(int l,int r,int pos)
{
if(l == r)
{
for(int i = 0;i < 5;i++)
for(int j = 0;j < 5;j++)
{
if(i == 0 && j == 0) a[pos].a[i][j] = (s[l] == '2');
else if(i == 1 && j == 1) a[pos].a[i][j] = (s[l] == '0');
else if(i == 2 && j == 2) a[pos].a[i][j] = (s[l] == '1');
else if(i == 3 && j == 3) a[pos].a[i][j] = (s[l] == '7') | (s[l] == '6');
else if(i == 4 && j == 4) a[pos].a[i][j] = (s[l] == '6');
else if(i == 0 && j == 1) a[pos].a[i][j] = ((s[l] == '2') ? 0 : inf);
else if(i == 1 && j == 2) a[pos].a[i][j] = ((s[l] == '0') ? 0 : inf);
else if(i == 2 && j == 3) a[pos].a[i][j] = ((s[l] == '1') ? 0 : inf);
else if(i == 3 && j == 4) a[pos].a[i][j] = ((s[l] == '7') ? 0 : inf);
else a[pos].a[i][j] = inf;
}
return;
}
int mid = (l + r) >> 1;
build(l,mid,pos << 1); build(mid + 1,r,pos << 1 | 1);
pushup(pos);
}
inline Matrix query(int l,int r,int L,int R,int pos)
{
if(L <= l && r <= R) return a[pos];
int mid = (l + r) >> 1;
if(L <= mid && R > mid) return query(l,mid,L,R,pos << 1) * query(mid + 1,r,L,R,pos << 1 | 1);
else if(L <= mid) return query(l,mid,L,R,pos << 1);
else if(R > mid) return query(mid + 1,r,L,R,pos << 1 | 1);
}
}t;
int main()
{
cin>>n>>q;
scanf("%s",s + 1);
t.build(1,n,1);
for(int i = 1,l,r;i <= q;i++)
{
cin>>l>>r;
Matrix now = t.query(1,n,l,r,1);
int ori[5] = {0,inf,inf,inf,inf},res[5] = {inf,inf,inf,inf,inf};
for(int j = 0;j < 5;j++)
for(int k = 0;k < 5;k++)
res[j] = min(res[j],ori[k] + now.a[k][j]);
printf("%d\n",(res[4] == inf) ? -1 : res[4]);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话