题目大意:给定一个长度为 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;
}

最新文章

  1. SQLSERVER走起微信公众帐号已经开通搜狗微信搜索
  2. ServerSocket的介绍
  3. 廖雪峰python教程的第一个疑问
  4. runtime 运行机制
  5. ACM: How many integers can you find-数论专题-容斥原理的简单应用+GCD
  6. x-code快捷键
  7. MINE
  8. RapidXml用法
  9. ZA7783:MIPI转LVDS/MIPI转RGB888/RGB转LVDS
  10. File API文件操作之FileReader二
  11. Linux 下软件的安装方法
  12. workerman——配置小程序的wss协议
  13. pycharm 的调试模式 MAC版
  14. 嵌入式 Linux 对内存的直接读写(devmem)
  15. sp_settriggerorder 设置触发器执行顺序
  16. 多线程学习笔记八之线程池ThreadPoolExecutor实现分析
  17. WP8.1学习系列(第十七章)——交互UX之输入和反馈模式
  18. SQL Server 安装后改动计算机名带来的问题以及解决方法
  19. spring-session实现分布式集群session的共享(转)
  20. Python核心编程——Chapter9

热门文章

  1. Python:Django 项目中可用的各种装备和辅助
  2. Linux常用目录名称
  3. numpy的logspace产生等比数列
  4. 非常好的一个JS代码(RelativePosition.js)
  5. Python3数据插MySQL中文乱码解决方案
  6. subquery 子查询
  7. Column常用的参数
  8. PTA(Basic Level)1032.挖掘机技术哪家强
  9. [转帖]2018年的新闻: 国内首家!腾讯主导Apache Hadoop新版本发布
  10. pom.xml标签页名称