The meaning of problems:
given a length \ (n-\) string, there are \ (Q \) a query, each challenge is an interval \ ([L, R & lt] \) , to be answered in the interval \ ([L , R & lt] \) , the minimum number required to delete the number, comprising meet interval \ (2017 \) of the sequence does not contain (2016 \) \ subsequences.
Ideas:
- Is not considered more interrogation, then the problem range \ (dp \) can be resolved, the state definition to the additional costs the state transition.
- Such as the current number is \ (7 \) , then obviously from the state (201 \) \ transferred from the need \ (0 \) cost; but if you do not \ (7 \) , then from the state \ (201 \) to state \ (201 \) you will need to \ (1 \) cost.
- Similarly, if the number is \ (6 \) , the preceding state if \ (201 \) or \ (2017 \) , the state can only be maintained at this time is clearly not the other metastasis, but also need to maintain \ (1 \ ) the cost of the job.
- We defined above is \ (0,1,2,3,4 \) represent the state \ (\ empty, 2,20,201,2017 \) , the state transition for each number has a definite price, which seems called finite state automaton?
- Consider a number of inquiries, as each question is asked more intervals, so we can expect to save a tree line segment information that is directly \ (dp \) hanging tree herd. (Interval \ (dp \) Support merge interval)
Wonderful ah.
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 200005;
int n, q;
char s[N];
struct node{
int a[5][5];
node() { memset(a, INF, sizeof(a)); }
node operator + (const node &other) const {
node res;
for(int i = 0; i < 5; i++) {
for(int j = 0; j < 5; j++) {
for(int k = 0; k < 5; k++) {
res.a[i][j] = min(res.a[i][j], a[i][k] + other.a[k][j]);
}
}
}
return res;
}
}tr[N << 2];
void build(int o, int l, int r) {
if(l == r) {
tr[o] = node();
for(int i = 0; i < 5; i++) tr[o].a[i][i] = 0;
if(s[l] == '2') tr[o].a[0][1] = 0, tr[o].a[0][0] = 1;
if(s[l] == '0') tr[o].a[1][2] = 0, tr[o].a[1][1] = 1;
if(s[l] == '1') tr[o].a[2][3] = 0, tr[o].a[2][2] = 1;
if(s[l] == '7') tr[o].a[3][4] = 0, tr[o].a[3][3] = 1;
if(s[l] == '6') tr[o].a[3][3] = tr[o].a[4][4] = 1;
return;
}
int mid = (l + r) >> 1;
build(o << 1, l, mid); build(o << 1|1, mid + 1, r);
tr[o] = tr[o << 1] + tr[o << 1|1];
}
node query(int o, int l, int r, int L, int R) {
if(L <= l && r <= R) return tr[o];
int mid = (l + r) >> 1;
if(R <= mid) return query(o << 1, l, mid, L, R);
if(L > mid) return query(o << 1|1, mid + 1, r, L, R);
return query(o << 1, l, mid, L, R) + query(o << 1|1, mid + 1, r, L, R);
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n >> q;
cin >> s + 1;
build(1, 1, n);
while(q--) {
int l, r; cin >> l >> r;
node ans = query(1, 1, n, l, r);
cout << (ans.a[0][4] > n ? -1 : ans.a[0][4]) << '\n';
}
return 0;
}