题目大意:给定一个长度为 N 的字符串,定义一个字串是“好的”,当且仅当字串中含有一个 “2017” 的子序列,且不含有 “2016” 的子序列。现给出 M 个询问,每次询问区间 [l, r] 内至少删去多少个字符才能使得该区间变成“好的”。

题解:

由于题目中要求的是子序列,且序列长度仅为 4,考虑状压,即:"" -> 0, “2” -> 1, "20" -> 2, "201" -> 3, "2017" -> 4。现假设只有一次询问的话,可以进行全局的一次 dp,状态为:dp[i][s] 表示到 i 下标为止,序列的状态是 s 需要删去的最小字符个数。可以发现转移方程仅与 i - 1 有关,又考虑到要回答区间 [l, r] 的询问,可以采用线段树维护矩阵乘法的形式。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
const int inf = 0x3f3f3f3f; char s[maxn];
int n, m;
struct matrix {
int mat[5][5];
matrix() {
memset(mat, 0x3f, sizeof(mat));
}
int *operator[](int x) {
return mat[x];
}
friend matrix operator*(matrix &x, matrix &y) {
matrix z;
for (int i = 0; i <= 4; i++) {
for (int j = 0; j <= 4; j++) {
for (int k = 0; k <= 4; k++) {
z[i][j] = min(z[i][j], x[i][k] + y[k][j]);
}
}
}
return z;
}
};
struct node {
#define ls(o) t[o].lc
#define rs(o) t[o].rc
int lc, rc;
matrix mat;
} t[maxn << 1];
int tot, rt;
inline void pull(int o) {
t[o].mat = t[ls(o)].mat * t[rs(o)].mat;
}
void build(int &o, int l, int r) {
o = ++tot;
if (l == r) {
for (int i = 0; i < 5; i++) t[o].mat[i][i] = 0;
if (s[l] == '2') t[o].mat[0][1] = 0, t[o].mat[0][0] = 1;
if (s[l] == '0') t[o].mat[1][2] = 0, t[o].mat[1][1] = 1;
if (s[l] == '1') t[o].mat[2][3] = 0, t[o].mat[2][2] = 1;
if (s[l] == '7') t[o].mat[3][4] = 0, t[o].mat[3][3] = 1;
if (s[l] == '6') t[o].mat[3][3] = 1, t[o].mat[4][4] = 1;
return;
}
int mid = l + r >> 1;
build(ls(o), l, mid);
build(rs(o), mid + 1, r);
pull(o);
}
matrix query(int o, int l, int r, int x, int y) {
if (l == x && r == y) {
return t[o].mat;
}
int mid = l + r >> 1;
if (y <= mid) {
return query(ls(o), l, mid, x, y);
} else if (x > mid) {
return query(rs(o), mid + 1, r, x, y);
} else {
matrix ansl = query(ls(o), l, mid, x, mid);
matrix ansr = query(rs(o), mid + 1, r, mid + 1, y);
return ansl * ansr;
}
} int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> s + 1;
build(rt, 1, n);
while (m--) {
int l, r;
cin >> l >> r;
int ans = query(rt, 1, n, l, r)[0][4];
cout << (ans == inf ? -1 : ans) << endl;
}
return 0;
}

【CF750E】New Year and Old Subsequence的更多相关文章

  1. 【Leetcode_easy】674. Longest Continuous Increasing Subsequence

    problem 674. Longest Continuous Increasing Subsequence solution class Solution { public: int findLen ...

  2. 【LeetCode】674. Longest Continuous Increasing Subsequence 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 动态规划 空间压缩DP 日期 题目地址:https: ...

  3. 【HDOJ】1423 Greatest Common Increasing Subsequence

    LCIS /* 1423 */ #include <cstdio> #include <cstring> #include <cstdlib> #define MA ...

  4. 【LeetCode】动态规划(下篇共39题)

    [600] Non-negative Integers without Consecutive Ones [629] K Inverse Pairs Array [638] Shopping Offe ...

  5. 【二分答案nlogn/标解O(n)】【UVA1121】Subsequence

    A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, a ...

  6. 【CF888E】Maximum Subsequence(meet in the middle)

    [CF888E]Maximum Subsequence(meet in the middle) 题面 CF 洛谷 题解 把所有数分一下,然后\(meet\ in\ the\ middle\)做就好了. ...

  7. 【CF888E】Maximum Subsequence 折半搜索

    [CF888E]Maximum Subsequence 题意:给你一个序列{ai},让你从中选出一个子序列,使得序列和%m最大. n<=35,m<=10^9 题解:不小心瞟了一眼tag就一 ...

  8. HDOJ 1423 Greatest Common Increasing Subsequence 【DP】【最长公共上升子序列】

    HDOJ 1423 Greatest Common Increasing Subsequence [DP][最长公共上升子序列] Time Limit: 2000/1000 MS (Java/Othe ...

  9. HDOJ 1159 Common Subsequence【DP】

    HDOJ 1159 Common Subsequence[DP] Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...

随机推荐

  1. docker pull / docker login 报错 Error response from daemon: Get https://registry-1.docker.io/v2/: x509

    docker pull 和 docker login 的时候报错 Error response from daemon: Get https://registry-1.docker.io/v2/: x ...

  2. 基于OpenCV的三维数据点的曲面重构_MySurefaceReconstruction

    在Opencv中有个Viz模块,可以显示三维物体,还可以实现三维动画,本来是很好的东东,但是里面的函数.类的说明太过简单,始终不得要领.不过其中一个扩展功能非常好,就是你可以在vtk中设计自己的模型类 ...

  3. Unity3D入门 UnityAPI常用方法和类

    时间函数: 这里只列举了一部分,更多的看Scripting API using System.Collections; using System.Collections.Generic; using ...

  4. flask 之(二) --- 视图|模版|模型

    Flask框架 打开pycharm编译器,新建一个Flask项目,选择提前建好的虚拟环境 . 项目结构: static:静态资源文件,可以直接被浏览器访问 templates:模版文件,必须在项目的p ...

  5. 编译安装MySQL数据库

    1. 安cmake工具 # yum install -y cmake 2. 创建mysql用户 # useradd -M -s /sbin/nologin mysql 3. 创建数据目录 # mkdi ...

  6. 2019牛客暑期多校训练营(第三场)- F Planting Trees

    题目链接:https://ac.nowcoder.com/acm/contest/883/F 题意:给定n×n的矩阵,求最大子矩阵使得子矩阵中最大值和最小值的差值<=M. 思路:先看数据大小,注 ...

  7. mysql jdbc url

    地址为jdbc:mysql://localhost:3306/mymiaosha?characterEncoding=utf-8时访问时可能会出现下图提示 地址改为jdbc:mysql://local ...

  8. Spring boot 整合CXF webservice 遇到的问题及解决

    将WebService的WSDL生成的代码的命令: wsimport -p com -s . com http://localhost:8080/service/user?wsdl Spring bo ...

  9. # C++中对PI的引用

    #include <iostream> #include <cmath> using namespace std; int main(){ printf("%.10l ...

  10. mysql的索引为什么要使用B+树而不是其他树?

    总结 1.InnoDB存储引擎的最小存储单元是页,页可以用于存放数据也可以用于存放键值+指针,在B+树中叶子节点存放数据,非叶子节点存放键值+指针. 2.索引组织表通过非叶子节点的二分查找法以及指针确 ...