Codeforces750E New Year and Old Subsequence (线段树维护矩阵)

题目链接

题解

用矩阵表示状态,用线段树维护子串转移
查看代码
#include <bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i = (a);i <= (b);++i)
typedef long long ll;
const int maxn = 2e5+5;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
ll qpow(ll a,ll b){ll res = 1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
char s[maxn];
struct Matrix
{
    int mat[5][5];//5种状态转换
    Matrix(){memset(mat,0x3f,sizeof(mat));};
    Matrix operator + (const Matrix &a)const
    {
        Matrix x;
        for(int i = 0;i < 5;++i){
            for(int j = 0;j < 5;++j){
                x.mat[i][j] = inf;
                for(int k = 0;k < 5;++k){
                    x.mat[i][j] = min(x.mat[i][j],mat[i][k]+a.mat[k][j]);
                }
            }
        }
        return x;
    }
};
struct Segment_tree
{
    Matrix tree[maxn<<2];
    void build(int root,int l,int r){
        if(l==r){
            for(int i = 0;i < 5;++i)tree[root].mat[i][i] = 0;
            if(s[l]=='2')tree[root].mat[0][0]=1,tree[root].mat[0][1]=0;
            else if(s[l]=='0')tree[root].mat[1][1]=1,tree[root].mat[1][2]=0;
            else if(s[l]=='1')tree[root].mat[2][2]=1,tree[root].mat[2][3]=0;
            else if(s[l]=='7')tree[root].mat[3][3]=1,tree[root].mat[3][4]=0;
            else if(s[l]=='6')tree[root].mat[3][3]=1,tree[root].mat[4][4]=1;
            return;
        }
        int mid = l+r>>1;
        build(root<<1,l,mid);
        build(root<<1|1,mid+1,r);
        tree[root] = tree[root<<1]+tree[root<<1|1];
    }
    Matrix query(int root,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr)return tree[root];
        int mid = l+r>>1;
        if(qr<=mid)return query(root<<1,l,mid,ql,qr);
        if(ql>mid)return query(root<<1|1,mid+1,r,ql,qr);
        return query(root<<1,l,mid,ql,qr)+query(root<<1|1,mid+1,r,ql,qr);
    }
}sg;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("simple.in","r",stdin);
    freopen("simple.out","w",stdout);
#endif
    int n,q;
    scanf("%d%d",&n,&q);
    scanf("%s",s+1);
    sg.build(1,1,n);
    while(q--){
        int l,r;
        scanf("%d%d",&l,&r);
        int tmp = sg.query(1,1,n,l,r).mat[0][4];
        if(tmp<=1e9)printf("%d\n",tmp);
        else printf("-1\n");
    }
    return 0;
}

posted @ 2020-09-10 19:30  tryatry  阅读(163)  评论(0编辑  收藏  举报