zoukankan      html  css  js  c++  java
  • CF750E New Year and Old Subsequence

    题目链接:CF750E New Year and Old Subsequence

    E. New Year and Old Subsequence

    time limit per test

    3 seconds

    memory limit per test

    256 megabytes

    input

    standard input

    output

    standard output

    A string t is called nice if a string "2017" occurs in t as a subsequence but a string "2016" doesn't occur in t as a subsequence. For example, strings "203434107" and "9220617" are nice, while strings "20016", "1234" and "20167" aren't nice.

    The ugliness of a string is the minimum possible number of characters to remove, in order to obtain a nice string. If it's impossible to make a string nice by removing characters, its ugliness is  - 1.

    Limak has a string s of length n, with characters indexed 1 through n. He asks you q queries. In the i-th query you should compute and print the ugliness of a substring (continuous subsequence) of s starting at the index a__i and ending at the index b__i (inclusive).

    Input

    The first line of the input contains two integers n and q (4 ≤ n ≤ 200 000, 1 ≤ q ≤ 200 000) — the length of the string s and the number of queries respectively.

    The second line contains a string s of length n. Every character is one of digits '0'–'9'.

    The i-th of next q lines contains two integers a__i and b__i (1 ≤ a__i ≤ b__i ≤ n), describing a substring in the i-th query.

    Output

    For each query print the ugliness of the given substring.

    Examples

    Input

    Copy

    8 3
    20166766
    1 8
    1 7
    2 8

    Output

    Copy

    4
    3
    -1

    Input

    Copy

    15 5
    012016662091670
    3 4
    1 14
    4 15
    1 13
    10 15

    Output

    Copy

    -1
    2
    1
    -1
    -1

    Input

    Copy

    4 2
    1234
    2 4
    1 2

    Output

    Copy

    -1
    -1

    Note

    In the first sample:

    • In the first query, ugliness("20166766") = 4 because all four sixes must be removed.
    • In the second query, ugliness("2016676") = 3 because all three sixes must be removed.
    • In the third query, ugliness("0166766") =  - 1 because it's impossible to remove some digits to get a nice string.

    In the second sample:

    • In the second query, ugliness("01201666209167") = 2. It's optimal to remove the first digit '2' and the last digit '6', what gives a string "010166620917", which is nice.
    • In the third query, ugliness("016662091670") = 1. It's optimal to remove the last digit '6', what gives a nice string "01666209170".

    题意: 在区间([l,r])中删去最少的字符数使得在这个区间内不含有子序列("2016")且含有子序列("2017"),如果无法满足条件,输出(-1).

    题解: 首先看到题目中要求区间的某个值,想到用某种数据结构来维护这个值.

    然而这个最小值似乎是要用(DP)来求的?

    那么这里就有点动态(DP)的意思了:我们将某个位置的状态加入矩阵中,再对这个序列开一棵线段树,线段树中的节点维护矩阵的状态.

    我们将("2017")拆成5份,分别是(empty,2,20,201,2017),用(0 o 4)表示这(5)个状态.

    我们设转移矩阵$$D=
    left[
    egin{matrix}
    a_{0,0} & ... & a_{0,4}
    a_{i,j-1} & a_{i,j} & a_{i,j+1}
    a_{4,0} & ... & a_{4,4}
    end{matrix}
    ight] ag{3}

    [其中$a_{i,j}$表示从$i$状态转移到$j$状态所需要的删去的字符数. 那么当我们枚举到一个位置的时候,假设这个位置是$2$,那么如果不删去字符显然会形成状态$1$,为了维持之前的状态$0$,则需要删去这个字符,删去的字符数为1.那么对于某一位为$2$,显然这位的转移矩阵为$$D= left[ egin{matrix} 1 & 0 & inf & inf & inf \ inf & 0 & inf & inf & inf \ inf & inf & 0 & inf & inf \ inf & inf & inf & 0 & inf \ inf & inf & inf & inf & 0 end{matrix} ight] ag{3} ]

    同理,对于该位为(0,1,7)都是一样的.

    但是如果该位为(6)呢?显然我们是不能让串中出现("2016")的,所以是一定要删除这个字符的,所以它的转移矩阵为$$D=
    left[
    egin{matrix}
    0 & inf & inf & inf & inf
    inf & 0 & inf & inf & inf
    inf & inf & 0 & inf & inf
    inf & inf & inf & 1 & inf
    inf & inf & inf & inf & 1
    end{matrix}
    ight] ag{3}

    [ 也就是说,如果串中已经出现了$"201"$或是$"2017"$,那么这个$6$就必须要删掉(或是其他位置删掉某个数字). 但是我们知道,矩阵乘法的运算法则是$c_{i,j}=sum_{k=1}^{n}a_{i,k}*b_{k,j}$,而我们这里是需要求一个最小值的,所以我们可以改一下矩阵的运算方法:$c_{i,j}=max{a_{i,k}+b_{k,j}},kin[1,n]$ 至于为什么这样是成立的,可以类比一下floyed求最短路更新的过程,因为这样的运算也是满足结合律的. 但是有点要注意,也就是矩阵乘法是不满足交换律的,也就是$A*B$不一定等于$B*A$,而线段树的$pushup$一般是将左儿子的矩阵乘到右儿子的矩阵上,所以要注意一下哪个矩阵放在左边(虽然这题矩阵的构造方法是统一的,也就是说这题不用考虑这个问题) 看代码理解一下吧. ```cpp #include<bits/stdc++.h> #define ll(x) (x << 1) #define rr(x) (x << 1 | 1) using namespace std; const int N = 2e5+5; const int inf = 0x3f3f3f3f; int n, m; char s[N]; struct Matrix{ int a[5][5]; Matrix(){ memset(a, 0x3f, sizeof(a)); } Matrix operator * (Matrix x){ Matrix res; for(int i = 0; i < 5; i++) for(int j = 0; j < 5; j++) for(int k = 0; k < 5; k++) res.a[i][j] = min(res.a[i][j], a[i][k]+x.a[k][j]); return res; } }; struct SegmentTree{ int l, r; Matrix M; }t[N*4]; void up(int x){ t[x].M = t[ll(x)].M*t[rr(x)].M; } void build(int x, int l, int r){ t[x].l = l, t[x].r = r; int mid = (l+r>>1); if(l == r){ for(int i = 0; i < 5; i++) t[x].M.a[i][i] = 0; if(s[l] == '2') t[x].M.a[0][0] = 1, t[x].M.a[0][1] = 0; if(s[l] == '0') t[x].M.a[1][1] = 1, t[x].M.a[1][2] = 0; if(s[l] == '1') t[x].M.a[2][2] = 1, t[x].M.a[2][3] = 0; if(s[l] == '7') t[x].M.a[3][3] = 1, t[x].M.a[3][4] = 0; if(s[l] == '6') t[x].M.a[3][3] = 1, t[x].M.a[4][4] = 1; return; } build(ll(x), l, mid), build(rr(x), mid+1, r); up(x); } Matrix query(int x, int l, int r){ if(l <= t[x].l && t[x].r <= r) return t[x].M; int mid = (t[x].l+t[x].r>>1); if(r <= mid) return query(ll(x), l, r); if(mid < l) return query(rr(x), l, r); return query(ll(x), l, r)*query(rr(x), l, r); } int main(){ ios::sync_with_stdio(false); int x, y; cin >> n >> m >> (s+1); build(1, 1, n); for(int i = 1; i <= m; i++){ cin >> x >> y; Matrix ans = query(1, x, y); cout << (ans.a[0][4] > n ? -1 : ans.a[0][4]) << endl; } return 0; } ```]

  • 相关阅读:
    课堂作业04 2017.10.27
    课程作业 03 动手动脑 2017.10.20
    课程作业 03 2017.10.20
    HDU 3974 Assign the task
    POJ 2155 Matrix
    POJ 2481 Cows
    HDU 3038 How Many Answers Are Wrong
    CS Academy Array Removal
    POJ_1330 Nearest Common Ancestors LCA
    CF Round 427 D. Palindromic characteristics
  • 原文地址:https://www.cnblogs.com/BCOI/p/10329108.html
Copyright © 2011-2022 走看看