Codeforcesグッバイ2016 E.正月と旧サブシーケンス

ポータル

問題の意味:
長所与(\ N-)\文字列がある\(Q \)クエリは、各チャレンジは間隔である\([L、R&LT] \)間隔で回答する、\([L 、R&LT] \) 番号を削除するために必要な最小の数であってミート間隔\(2017 \)配列が含まれていない(2016 \)\サブ配列を。

アイデア:

  • より多くの質問は、問題の範囲とはみなされません\(DP \)を解決することができ、追加コストの状態の定義の状態遷移。
  • 現在の数があるような\(7 \) その後、明らかに状態から(201 \)\必要性から転送された\(0 \)コスト;しかし、あなたがいない場合は(7 \)を\、状態から\(201 \)の状態に\ (201 \)あなたがする必要があります(1 \)\コストを。
  • 数値の場合同様、(6 \)を\場合、前の状態を\(201 \)または\(2017 \) 状態は、この時点で維持することができ、明らかに他の転移ではなく、また、維持する必要が\(1 \を)ジョブのコスト。
  • 我々は、上記に定義されている\(0,1,2,3,4 \)状態表現(空\、2,20,201,2017が\)\を、各数値の状態遷移はそう明確な価格を持っています有限状態オートマトンと呼ばれますか?
  • 各質問は、より多くの間隔を尋ねているので、私たちが直接である木の線分情報を保存することを期待することができますよう、問い合わせの数を考えてみましょう(DP \)\ツリーの群れをぶら下げ。(インターバル\(DP \)のサポートマージ間隔)

ワンダフルああ。

#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;
}

おすすめ

転載: www.cnblogs.com/heyuhhh/p/11491321.html