【2019 南昌网络赛】Hello 2019(线段树、矩阵、dp)

A digital string is “good”: when it contains a subsequence 91029102 and does not contain a subsequence 81028102.

The bad value of a string is defined as how many characters are to remove at least, so that the string satisfies the “good” property. Output -1 if the string cannot satisfy the “good” property by removing some characters (0 or maybe more).

Input
The first line contains two integers n , Q ( 1 ≤ n , Q ≤ 2 ∗ 1 0 5 ) n,Q(1\leq n,Q\leq2*10^5) n,Q(1n,Q2105) n is the length of the string and Q is the number of queries.

The second line contains a string s that consists entirely of decimal numbers.

The next Q line, each line contains two integers l , r ( 1 ≤ l ≤ r ≤ n ) l,r(1≤l≤r≤n) l,r(1lrn), denoting a query.

Output
For each query, output an answer which is the bad value of the substring s l s l + 1 ⋯ s r s_ls_{l+1} \cdots s_r slsl+1srfrom s.

样例输入
8 3
88988102
1 8
2 8
1 7
样例输出
4
3
-1
代码:

#include
#include
#include
#include
#define INF 0x3f3f3f3f
using namespace std;
const int maxx = 200005;
struct node
{
    int f[5][5];
    void init()
    {
        memset(f,INF,sizeof(f));
        for(int i=0;i<5;i++)f[i][i]=0;
    }
    friend node operator *(node x1,node x2)
    {
        node tmp;
        for(int i=0;i<5;i++)
            for(int j=0;j<5;j++)
            {
                tmp.f[i][j]=INF;
                for(int k=0;k<5;k++)
                    tmp.f[i][j]=min(tmp.f[i][j],x1.f[i][k]+x2.f[k][j]);
            }
        return tmp;
    }
}c[maxx<<2];
char a[maxx];
void build(int s,int l,int r)
{
    if(l==r)
    {
        int x=a[l]-'0';
        c[s].init();
        if(x==2)c[s].f[0][0]=1,c[s].f[0][1]=0;
        if(x==0)c[s].f[1][1]=1,c[s].f[1][2]=0;
        if(x==1)c[s].f[2][2]=1,c[s].f[2][3]=0;
        if(x==9)c[s].f[3][3]=1,c[s].f[3][4]=0;
        if(x==8) c[s].f[3][3]=1,c[s].f[4][4]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(s<<1,l,mid);
    build(s<<1|1,mid+1,r);
    c[s]=c[s<<1]*c[s<<1|1];
}
node query(int s,int l,int r,int L,int R)
{
    if(L<=l&&r<=R)return c[s];
    int mid=(l+r)>>1;
    node ans;ans.init();
    if(mid>=L)ans=ans*query(s<<1,l,mid,L,R);
    if(mid<R)ans=ans*query(s<<1|1,mid+1,r,L,R);
    return ans;
}
int n,m;
int main()
{
    cin>>n>>m;
    scanf("%s",a+1);
    reverse(a+1,a+1+n);
    //printf("%s\n",a+1);
    build(1,1,n);
    int l,r;
    while(m--)
    {
        scanf("%d%d",&l,&r);
        l=n+1-l;
        r=n+1-r;
        int ans=query(1,1,n,r,l).f[0][4];
        printf("%d\n",ans==INF?-1:ans);

    }
    return 0;
}

你可能感兴趣的:(线段树)