链接
题意:求一段序列中包含9102不包含8102是删去的最少字符。
从后向前找,用矩阵维护
0:原始
1:2
2:20
3:201
4:2019
区间询问,考虑线段树,维护区间的最少删去次数,当有8时修改一下。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=2e5+5;
int n,q;
char s[maxn];
struct node{
int mat[5][5];
node operator +(node x){
node ans;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
ans.mat[i][j]=maxn;
for(int k=0;k<5;k++){
ans.mat[i][j]=min(ans.mat[i][j],mat[i][k]+x.mat[k][j]);
}
}
}
return ans;
}
}a[maxn<<2];
void build(int n,int l,int r){
if(l==r){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
if(i==j){
a[n].mat[i][j]=0;
}
else a[n].mat[i][j]=maxn;
}
}
if(s[l]=='2')a[n].mat[0][1]=0,a[n].mat[0][0]=1;
if(s[l]=='0')a[n].mat[1][2]=0,a[n].mat[1][1]=1;
if(s[l]=='1')a[n].mat[2][3]=0,a[n].mat[2][2]=1;
if(s[l]=='9')a[n].mat[3][4]=0,a[n].mat[3][3]=1;
if(s[l]=='8')a[n].mat[3][3]=1,a[n].mat[4][4]=1;
return;
}
int mid=(l+r)>>1;
build(n<<1,l,mid);
build(n<<1|1,mid+1,r);
a[n]=a[n<<1]+a[n<<1|1];
}
node query(int n,int L,int R,int l,int r){
if(L>=l&&R<=r){
return a[n];
}
int mid=(L+R)>>1;
if(mid<l)return query(n<<1|1,mid+1,R,l,r);
if(mid>=r)return query(n<<1,L,mid,l,r);
return query(n<<1,L,mid,l,r)+query(n<<1|1,mid+1,R,l,r);
}
int main(){
scanf("%d%d",&n,&q);
for(int i=n;i>=1;i--){
cin>>s[i];
}
build(1,1,n);
int l,r;
while(q--){
scanf("%d%d",&l,&r);
int ans=query(1,1,n,n-r+1,n-l+1).mat[0][4];
if(ans==maxn)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}
cf-750E
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=2e5+5;
char s[maxn];
struct node{
int mat[5][5];
node operator +(node x){
node ans;
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
ans.mat[i][j]=maxn;
for(int k=0;k<5;k++){
ans.mat[i][j]=min(ans.mat[i][j],mat[i][k]+x.mat[k][j]);
}
}
}
return ans;
}
}a[maxn<<2];
void build(int l,int r,int x) {
if(l==r) {
for(int i=0;i<5;++i) {
for(int j=0;j<5;++j) {
a[x].mat[i][j]=(i==j)?0:maxn;
}
}
if(s[l]=='2') a[x].mat[0][1]=0,a[x].mat[0][0]=1;
if(s[l]=='0') a[x].mat[1][2]=0,a[x].mat[1][1]=1;
if(s[l]=='1') a[x].mat[2][3]=0,a[x].mat[2][2]=1;
if(s[l]=='7') a[x].mat[3][4]=0,a[x].mat[3][3]=1;
if(s[l]=='6') a[x].mat[3][3]=1,a[x].mat[4][4]=1;
return ;
}
int m=l+r>>1;
build(l,m,x<<1);build(m+1,r,x<<1|1);
a[x]=a[x<<1]+a[x<<1|1];
}
node query(int l,int r,int L,int R,int x) {
if(L<=l&&r<=R) return a[x];
int m=l+r>>1;
if(m<L) return query(m+1,r,L,R,x<<1|1);
if(m>=R) return query(l,m,L,R,x<<1);
return query(l,m,L,R,x<<1)+query(m+1,r,L,R,x<<1|1);
}
int main(){
int N,q;
scanf("%d%d",&N,&q);
scanf("%s",s+1);
build(1,N,1);
int l,r;
while(q--){
scanf("%d%d",&l,&r);
int ans=query(1,N,l,r,1).mat[0][4];
if(ans==maxn)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}