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, Qn,Q(1\leq n,Q\leq2*10^5)(1≤n,Q≤2∗105). Where nn is the length of the string and QQ is the number of queries.
The second line contains a string ss that consists entirely of decimal numbers.
The next QQ line, each line contains two integers l, rl,r(1\leq l\leq r\leq n)(1≤l≤r≤n), denoting a query.
Output
For each query, output an answer which is the bad value of the substring s_ls_{l+1} \cdots s_rslsl+1⋯sr from ss.
样例
8 3 88988102 1 8 2 8 1 7
样例
4 3 -1
题意:给了一个长度为n只包含数字的字符串,m个区间询问,问对于每一次区间询问 [ l , r ] 需要去掉多少个字符才能使区间有9102没有8102. 反过来看的话就是只有 2019 没有 2018. 如果不能达成,则输出 -1.
思路:对于总区间来说,求最少的去掉个数就是一个dp。dp[ i ][ j ] 表示从 i 状态到达 j 状态的最小花费。由于只有5个字符对结果有影响,因此,将2重定义为0、0重定义为1、1重定义为2、9重定义为3、8重定义为4;又因为任意的dp都可以转化成矩阵来维护,而我们要查询的是区间的dp值,所以我们使用线段树来维护矩阵。
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define N 200010
using namespace std;
char s[N];
struct node{
int a[5][5];
node(){memset(a,inf,sizeof(a));}
node operator * (node b){
node ans;
for(int k=0;k<5;k++){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]);
}
}
}
return ans;
}
void push(int x){
for(int i=0;i<5;i++)a[i][i]=0;
if(x==2)a[0][0]=1,a[0][1]=0;
else if(x==0)a[1][1]=1,a[1][2]=0;
else if(x==1)a[2][2]=1,a[2][3]=0;
else if(x==9)a[3][3]=1,a[3][4]=0;
else if(x==8)a[3][3]=1,a[4][4]=1;
}
}Sum[N<<2];
void build(int l,int r,int o){
if(l==r){
Sum[o].push(s[l]-'0');
return;
}
int mid = (l + r)>>1;
build(l,mid,o<<1);
build(mid+1,r,o<<1|1);
Sum[o] = Sum[o<<1|1] * Sum[o<<1];
}
node query(int x,int y,int l,int r,int o){
if(l>=x&&r<=y)return Sum[o];
int mid=(l+r)>>1;
if(x<=mid&&y>mid) return query(x,y,mid+1,r,o<<1|1)*query(x,y,l,mid,o<<1);
if(y>mid)return query(x,y,mid+1,r,o<<1|1);
return query(x,y,l,mid,o<<1);
}
inline int read() {
int x = 0 , f = 1 ; char c = getchar() ;
while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
return x * f ;
}
int main(){
int n,q;
n=read();
q=read();
scanf("%s",s+1);
build(1,n,1);
for(int i=1;i<=q;i++){
int l,r;
l=read();
r=read();
int ans=query(l,r,1,n,1).a[0][4];
printf("%d\n",ans==inf?-1:ans);
}
return 0;
}