题意
给出一个长度为n的数字序列,每次询问给出一个区间[l,r],问至少要删掉多少个字符才能使”2017”是该区间的子序列且”2016”不是该区间的子序列。
n,q<=200000
分析
引入子序列自动机的思想:
设状态0表示空串,状态1表示走到了状态”2”,状态2表示都到了”20”,状态3表示走到”201”,状态4表示走到”2017”。
设f[i,j]表示在走到该区间之前走到了状态i,且在走完该区间后走到了状态j,最少需要删掉多少个字符。
如果知道左右区间的状态的话这两个矩阵显然是可以合并的。
那么只要用线段树来维护这个dp的转移即可。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=200005;
const int inf=1000000000;
int n,q;
char str[N];
struct Matrix
{
int a[5][5];
void unit(int c)
{
for (int i=0;i<=4;i++)
for (int j=0;j<=4;j++)
a[i][j]=(i==j)?0:inf;
if (c==-1) a[0][