Description

题库链接

给出一个长度为 \(n\) 的仅包含数字的字符串。 \(q\) 次询问,每次询问该串 \([a,b]\) 段内删去几个数能够使其不含 \(2016\) 的子串,但存在 \(2017\) 的子串。

\(4\leq n\leq 200000,1\leq q\leq 200000\)

Solution

考虑朴素的 \(DP\) 。我们记 \(f_{i,j}\) 为匹配到 \(i\) 这个位置拼成 "" "2" "20" "201" "2017" 的最小花费。显然这个是 \(O(nq)\) 的。

但对于每一位的转移是独立的。所以我们考虑用矩乘优化,线段树维护。

Code

//It is made by Awson on 2018.2.7
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 200000;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, q, a, b;
char ch[N+5];
struct mat {
int a[5][5];
mat() {memset(a, 127/3, sizeof(a)); }
mat(int **_a) {for (int i = 0; i < 5; i++) for (int j = 0; j < 5; j++) a[i][j] = _a[i][j]; }
mat operator * (const mat &b) const {
mat ans;
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++)
for (int k = 0; k < 5; k++)
ans.a[i][j] = Min(ans.a[i][j], a[i][k]+b.a[k][j]);
return ans;
}
};
struct Segment_tree {
mat sgm[(N<<2)+5];
#define lr(x) (x<<1)
#define rr(x) (x<<1|1)
void build(int o, int l, int r) {
if (l == r) {
for (int i = 0; i < 5; i++) sgm[o].a[i][i] = 0;
if (ch[l] == '2') sgm[o].a[0][0] = 1, sgm[o].a[0][1] = 0;
else if (ch[l] == '0') sgm[o].a[1][1] = 1, sgm[o].a[1][2] = 0;
else if (ch[l] == '1') sgm[o].a[2][2] = 1, sgm[o].a[2][3] = 0;
else if (ch[l] == '7') sgm[o].a[3][3] = 1, sgm[o].a[3][4] = 0;
else if (ch[l] == '6') sgm[o].a[3][3] = 1, sgm[o].a[4][4] = 1;
return;
}
int mid = (l+r)>>1;
build(lr(o), l, mid), build(rr(o), mid+1, r);
sgm[o] = sgm[lr(o)]*sgm[rr(o)];
}
mat query(int o, int l, int r, int a, int b) {
if (a <= l && r <= b) return sgm[o];
int mid = (l+r)>>1;
if (b <= mid) return query(lr(o), l, mid, a, b);
if (a > mid) return query(rr(o), mid+1, r, a, b);
return query(lr(o), l, mid, a, b)*query(rr(o), mid+1, r, a, b);
}
}T; void work() {
read(n), read(q); scanf("%s", ch+1);
T.build(1, 1, n);
while (q--) {
read(a), read(b);
mat tmp = T.query(1, 1, n, a, b);
writeln(tmp.a[0][4] > n ? -1 : tmp.a[0][4]);
}
}
int main() {
work(); return 0;
}

[Codeforces 750E]New Year and Old Subsequence的更多相关文章

  1. Codeforces 750E New Year and Old Subsequence - 线段树 - 动态规划

    A string t is called nice if a string "2017" occurs in t as a subsequence but a string &qu ...

  2. Codeforces 750E New Year and Old Subsequence 线段树 + dp (看题解)

    New Year and Old Subsequence 第一感觉是离线之后分治求dp, 但是感觉如果要把左边的dp值和右边的dp值合起来, 感觉很麻烦而且时间复杂度不怎么对.. 然后就gun取看题解 ...

  3. Codeforces 750E - New Year and Old Subsequence(线段树维护矩阵乘法,板子题)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 我做这道 *2600 的动力是 wjz 出了道这个套路的题,而我连起码的思路都没有,wtcl/kk 首先考虑怎样对某个固定的串计 ...

  4. 【codeforces 750E】New Year and Old Subsequence

    time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  5. New Year and Old Subsequence CodeForces - 750E (dp矩阵优化)

    大意: 给定字符串, 每次询问区间[l,r]有子序列2017, 无子序列2016所需要删除的最小字符数 转移用矩阵优化一下, 要注意$(\mathbb{Z},min,+)$的幺元主对角线全0, 其余全 ...

  6. Educational Codeforces Round 32:E. Maximum Subsequence(Meet-in-the-middle)

    题目链接:E. Maximum Subsequence 用了一个Meet-in-the-middle的技巧,还是第一次用到这个技巧,其实这个技巧和二分很像,主要是在dfs中,如果数量减小一半可以节约很 ...

  7. Codeforces Round #646 (Div. 2) B. Subsequence Hate(前缀和)

    题目链接:https://codeforces.com/contest/1363/problem/B 题意 可以将 $01$ 串中的 $0$ 变为 $1$.$1$ 变为 $0$,问至少需要变换多少字符 ...

  8. Codeforces 750E 线段树DP

    题意:给你一个字符串,有两种操作:1:把某个位置的字符改变.2:询问l到r的子串最少需要删除多少个字符,使得这个子串含有2017子序列,并且没有2016子序列? 思路:线段树上DP,我们设状态0, 1 ...

  9. Codeforces Round #646 (Div. 2) B. Subsequence Hate (思维,前缀和)

    题意:给你一个只含有\(0\)和\(1\)的字符串,每次操作可以将\(0\)改成\(1\)或\(1\)改成\(0\),问最少操作多少次,使得子序列中不含有\(010\)和\(101\). 题解:仔细想 ...

随机推荐

  1. Java基础学习笔记六 Java基础语法之类和ArrayList

    引用数据类型 引用数据类型分类,提到引用数据类型(类),其实我们对它并不陌生,如使用过的Scanner类.Random类.我们可以把类的类型为两种: 第一种,Java为我们提供好的类,如Scanner ...

  2. java Classpath 的解读

    在了解java的classpath之前先来看看java的运行机制  1.首先是编译,将.java文件编译成虚拟机认识的二进制文件.这个过程需要的命令是javac  可以在jdk的bin目录中找到,ja ...

  3. 项目Beta冲刺第一天

    1.昨天的困难,今天解决的进度,以及明天要做的事情 昨天的困难:企业自查风险模块仍旧存在部分问题,没有什么大的困难,主要是需求问题,企业人员什么条件之下可以添加风险点,第三方评估人员是否可以上报风险, ...

  4. 单向链表在O(1)时间内删除一个节点

    说删链表节点,第一时间想到就是遍历整个链表,找到删除节点的前驱,改变节点指向,删除节点,但是,这样删除单链表的某一节点,时间复杂度就是O(n),不符合要求: 时间复杂度是O(n)的做法就不说了,看看O ...

  5. 基于协程的Python网络库gevent

    import gevent def test1(): print 12 gevent.sleep(0) print 34 def test2(): print 56 gevent.sleep(0) p ...

  6. 【iOS】swift 排序Sort函数用法(包含NSDictionary排序)

    用了几分钟做的简单翻译 一个例子 直接贴代码,不过多解释 //这是我们的model class imageFile { var fileName = String() var fileID = Int ...

  7. Hibernate之HQL

    SQL语句的DML操作不外乎:增,删,改,查 增加 :  save(),persist() 删除 :   delete() 改动 :   update() 查询  :  get() ,load() 其 ...

  8. DOM中的事件对象(event)

    在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件相关的信息. 包括导致事件的元素.事件的类型以及其他与特定事件相关的信息. 例如:鼠标操作导致的事件对象中,会包含鼠 ...

  9. 《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet

    软件:Cisco Packet Tracer Instructor 软件下载链接在上一篇文章中. 内容:通过设置三个密码,熟悉采用Telnet方式配置交换机的方法. 细节说明:计算机的IP地址和交换机 ...

  10. Python内置函数(30)——super

    英文文档: super([type[, object-or-type]]) Return a proxy object that delegates method calls to a parent ...