zoukankan      html  css  js  c++  java
  • 【codeforces 750E】New Year and Old Subsequence

    time limit per test3 seconds
    memory limit per test256 megabytes
    inputstandard input
    outputstandard 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 ai and ending at the index bi (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 ai and bi (1 ≤ ai ≤ bi ≤ n), describing a substring in the i-th query.

    Output
    For each query print the ugliness of the given substring.

    Examples
    input
    8 3
    20166766
    1 8
    1 7
    2 8
    output
    4
    3
    -1
    input
    15 5
    012016662091670
    3 4
    1 14
    4 15
    1 13
    10 15
    output
    -1
    2
    1
    -1
    -1
    input
    4 2
    1234
    2 4
    1 2
    output
    -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”.

    【题目链接】:http://codeforces.com/contest/750/problem/E

    【题解】

        merge矩阵(dp)+线段树;
        m[i][j]表示从状态i->j转移的花费;
        0表示什么都没有
        1表示出现了2
        2表示出现了20
        3表示出现了201
        4表示出现了2017
        出现了2,20,则遇到6的时候我么可以不用管;
        但是如果出现了2012017,然后又遇到了6,则我们需要把这个6删掉; 
        for (i = 0;i <= 4;i++)//除了遇到2,0,1,6,7这5个特别的数字之外,
            m[i][i] = 0;//遇到的时候状态都不会变;所以不用花费(操作);
        if (ch == '2')
        {
            m[0][0] = 1;//什么都没有->什么都没有,删掉这个2
            m[0][1] = 0;//什么都没有->出现了2,花费变成0
            //注意这里m[1][1] = 0,表示从出现了一个2到出现了一个2可以不用删掉任何东西,因为加上一个2也无妨,下面的解释就省略了,希望大家能看得明白.
        }
        if (ch=='0')
        {
            m[1][1] = 1 ;//出现了一个2->出现了一个2,则把0删掉
            m[1][2] = 0;//从出现一个2->出现了20,因为当前就是0,所以什么都不用加
        }
        if (ch=='1')
        {
            ma[2][2] = 1;//出现了20->出现了20,则把1删掉
            ma[2][3] = 0;//出现了20->出现了201,因为刚好遇到一个1则什么都不加
        }
        if (ch=='7')
        {
            m[3][3] = 1;//出现了201->出现了201,则把遇到的7删掉
            m[3][4] = 0;//出现了201->出现了2017,刚好遇到7,则什么都不做
        }
        if (ch=='6')
        {
            a[3][3] = 1;//出现了201->出现了数字6,则一定要把6删掉,不然无法满足题意
            a[4][4] = 1;//出现了2017->出现了数字6,则也一定要把6删掉.
        }
        线段树加一个合并操作就好;
        那个合并的操作和floyd算法类似;
        最后输出m[0][4];表示从什么都没有然后出现"2017"


    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int MAXN = 2e5+10;
    const int INF = 7e8;
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    
    struct abc
    {
        int m[5][5];
        friend abc operator * (abc a,abc b)
        {
            abc d;
            rep1(i,0,4)
                rep1(j,0,4)
                {
                    d.m[i][j] = INF;
                    rep1(k,0,4)
                        d.m[i][j] = min(d.m[i][j],a.m[i][k]+b.m[k][j]);
                }
            return d;
        }
    };
    
    int n,q;
    abc a[MAXN*4];
    char s[MAXN];
    
    void build(int l,int r,int rt)
    {
        if (l==r)
        {
            char ch = s[l];
            rep1(i,0,4)
                rep1(j,0,4)
                    a[rt].m[i][j] = (i==j)?0:INF;
            if (ch == '2')
            {
                a[rt].m[0][0] = 1;
                a[rt].m[0][1] = 0;
            }
            if (ch=='0')
            {
                a[rt].m[1][1] = 1;
                a[rt].m[1][2] = 0;
            }
            if (ch=='1')
            {
                a[rt].m[2][2] = 1;
                a[rt].m[2][3] = 0;
            }
            if (ch=='7')
            {
                a[rt].m[3][3] = 1;
                a[rt].m[3][4] = 0;
            }
            if (ch=='6')
            {
                a[rt].m[3][3] = 1;
                a[rt].m[4][4] = 1;
            }
            return;
        }
        int m = (l+r)>>1;
        build(lson);build(rson);
        a[rt] = a[rt<<1]*a[rt<<1|1];
    }
    
    abc query(int L,int R,int l,int r,int rt)
    {
        if (L<=l && r <= R)
            return a[rt];
        int m = (l+r)>>1;
        abc temp1,temp2;
        bool f1 = 0,f2 = 0;
        if (L <= m)
        {
            temp1 = query(L,R,lson);
            f1 = 1;
        }
        if (m < R)
        {
            temp2 = query(L,R,rson);
            f2 = 1;
        }
        if (f1&&f2)
            return temp1*temp2;
        if (f1)
            return temp1;
        if (f2)
            return temp2;
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        rei(n);rei(q);
        scanf("%s",s+1);
        build(1,n,1);
        rep1(i,1,q)
        {
            int L,R;
            rei(L);rei(R);
            int ans = query(L,R,1,n,1).m[0][4];
            if (ans>=INF)
                puts("-1");
            else
                cout << ans << endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    Codeforces Round #445 A. ACM ICPC【暴力】
    “玲珑杯”ACM比赛 Round #1
    HDU 6034 Balala Power!【排序/进制思维】
    2017多校训练1
    POJ 3620 Avoid The Lakes【DFS找联通块】
    Educational Codeforces Round 1D 【DFS求联通块】
    Openjudge1388 Lake Counting【DFS/Flood Fill】
    洛谷 P1506 拯救oibh总部【DFS/Flood Fill】
    小白书 黑白图像【DFS/Flood Fill】
    SSOJ 2316 面积【DFS/Flood Fill】
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626740.html
Copyright © 2011-2022 走看看