1. 程式人生 > >[Codeforces 750E]New Year and Old Subsequence

[Codeforces 750E]New Year and Old Subsequence

ons lin def aws swa rip 我們 can space

Description

題庫鏈接

給出一個長度為 \(n\) 的僅包含數字的字符串。 \(q\) 次詢問,每次詢問該串 \([a,b]\) 段內刪去幾個數能夠使其不含 \(2016\) 的子串,但存在 \(2017\) 的子串。

\(4\leq n\leq 200000,1\leq q\leq 200000\)

Solution

考慮樸素的 \(DP\) 。我們記 \(f_{i,j}\) 為匹配到 \(i\) 這個位置拼成 "" "2" "20" "201" "2017" 的最小花費。顯然這個是 \(O(nq)\) 的。

但對於每一位的轉移是獨立的。所以我們考慮用矩乘優化,線段樹維護。

Code

//It is made by Awson on 2018.2.7
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n')) #define lowbit(x) ((x)&(-(x))) using namespace std; const int N = 200000; void read(int &x) { char ch; bool flag = 0; for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); for (x = 0; isdigit(ch); x = (x<<1
)+(x<<3)+ch-48, ch = getchar()); x *= 1-2*flag; } void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); } void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, q, a, b; char ch[N+5]; struct mat { int a[5][5]; mat() {memset(a, 127/3, sizeof(a)); } mat(int **_a) {for (int i = 0; i < 5; i++) for (int j = 0; j < 5; j++) a[i][j] = _a[i][j]; } mat operator * (const mat &b) const { mat ans; for (int i = 0; i < 5; i++) for (int j = 0; j < 5; j++) for (int k = 0; k < 5; k++) ans.a[i][j] = Min(ans.a[i][j], a[i][k]+b.a[k][j]); return ans; } }; struct Segment_tree { mat sgm[(N<<2)+5]; #define lr(x) (x<<1) #define rr(x) (x<<1|1) void build(int o, int l, int r) { if (l == r) { for (int i = 0; i < 5; i++) sgm[o].a[i][i] = 0; if (ch[l] == '2') sgm[o].a[0][0] = 1, sgm[o].a[0][1] = 0; else if (ch[l] == '0') sgm[o].a[1][1] = 1, sgm[o].a[1][2] = 0; else if (ch[l] == '1') sgm[o].a[2][2] = 1, sgm[o].a[2][3] = 0; else if (ch[l] == '7') sgm[o].a[3][3] = 1, sgm[o].a[3][4] = 0; else if (ch[l] == '6') sgm[o].a[3][3] = 1, sgm[o].a[4][4] = 1; return; } int mid = (l+r)>>1; build(lr(o), l, mid), build(rr(o), mid+1, r); sgm[o] = sgm[lr(o)]*sgm[rr(o)]; } mat query(int o, int l, int r, int a, int b) { if (a <= l && r <= b) return sgm[o]; int mid = (l+r)>>1; if (b <= mid) return query(lr(o), l, mid, a, b); if (a > mid) return query(rr(o), mid+1, r, a, b); return query(lr(o), l, mid, a, b)*query(rr(o), mid+1, r, a, b); } }T; void work() { read(n), read(q); scanf("%s", ch+1); T.build(1, 1, n); while (q--) { read(a), read(b); mat tmp = T.query(1, 1, n, a, b); writeln(tmp.a[0][4] > n ? -1 : tmp.a[0][4]); } } int main() { work(); return 0; }

[Codeforces 750E]New Year and Old Subsequence