题目链接
题解
用矩阵表示状态,用线段树维护子串转移
查看代码
#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;
}