• Educational Codeforces Round 89 (Rated for Div. 2)


    传送门
    视频题解

    A. Shovels and Swords

    贪心。每次尽可能取较多那一边即可。
    写法上可以加速,((2,1),(1,2))这种可以看作((3,3)),只取((1,2))这种解个方程即可。
    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/11 22:36:15
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    
    void run() {
        int a, b; cin >> a >> b;
        if (a > b) swap(a, b);
        int x = min(b / 2, min(a, b - a));
        b -= 2 * x;
        a -= x;
        int ans = x;
        int c = min(a, b);
        ans += c / 3 * 2;
        a -= c / 3 * 3;
        b -= c / 3 * 3;
        if (a > b) swap(a, b);
        for (int i = 3; i >= 0; i--) {
            if (i <= a && 2 * i <= b) {
                ans += i;
                break;   
            }
        }
        cout << ans << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    B. Shuffle

    按题意模拟即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/11 22:44:42
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define l first
    #define r second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    
    void run() {
        int n, m, x;
        cin >> n >> x >> m;
        vector <pii> a(m);
        
        for (int i = 0; i < m; i++) {
            int l, r; cin >> l >> r;
            a[i] = MP(l, r);
        }
        
        int Min = x, Max = x;
        for (int i = 0; i < m; i++) {
            if (min(a[i].r, Max) >= max(a[i].l, Min)) {
                Min = min(a[i].l, Min);
                Max = max(a[i].r, Max);
            }
        }
        cout << Max - Min + 1 << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    C. Palindromic Paths

    找出矩阵所有对称的斜线就行。代码中有些细节,边界情况要注意一下。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/11 22:55:58
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    
    void run() {
        int n, m; cin >> n >> m;
        vector <vector <int>> a(n, vector <int>(m));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> a[i][j];
            }
        }
        int t = n + m - 1;
        int d = t / 2;
        int ans = 0;
        for (int k = 0; k < d; k++) {
            vector <vector <int>> cnt(2, vector <int>(2));
            int i = 0, j = k;
            if (j >= m) {
                i += j - m + 1;
                j = m - 1;
            }
            while (j >= 0 && i < n) {
                ++cnt[0][a[i][j]];
                ++i, --j;
            }
            i = n - 1, j = m - 1 - k;
            if (j < 0) {
                i += j;
                j = 0;
            }
            while (j < m && i >= 0) {
                ++cnt[1][a[i][j]];
                --i, ++j;
            }
            ans += min(cnt[0][0] + cnt[1][0], cnt[0][1] + cnt[1][1]);
        }
        cout << ans << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    D. Two Divisors

    (a_i=p_1^{q_1}*p_2^{q_2}*cdots *p_k^{q_k})构造(d_1=p_1^{q_1},d_2=frac{a_i}{d_1})就行。
    因为有这个式子:

    • (x,y)互质,则(gcd(x+y,xy)=1)

    证明的话视频里面有,主要就是用到两个关于(gcd)的性质:

    • (gcd(a,b)=gcd(a+b,b));
    • (gcd(a,c)=1),则(gcd(a,bc)=gcd(a,b))

    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/11 23:23:11
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 5e5 + 5, M = 2e7 + 5;
     
    int n;
     
    int cnt;
    int p[M];
    bool chk[M];
    void init() {
        for(int i = 2; i < M; i++) {
            if(!chk[i]) p[++cnt] = i;
            for(int j = 1; j <= cnt && 1ll * i * p[j] < M; j++) {
                chk[i * p[j]] = 1;
                if (i % p[j] == 0) {
                    break;
                }
            }
        }
    } 
     
    pii ans[N];
     
    void run() {
        cin >> n;
        for (int i = 1; i <= n; i++) {
            int x; cin >> x;
            int tmp = x;
            vector <int> v;
            for (int j = 1; j <= cnt; j++) {
                if (1ll * p[j] * p[j] > x) {
                    break;
                }
                if (x % p[j] == 0) {
                    int t = 1;
                    while (x % p[j] == 0) {
                        x /= p[j];
                        t *= p[j];
                    }
                    v.push_back(t);
                }
            }
            if (x > 1) {
                v.push_back(x);
            }
            if (sz(v) < 2) {
                v = {-1, -1};
            } else {
                v = {v[0], tmp / v[0]};
            }
            ans[i] = MP(v[0], v[1]);
        }
        for (int i = 1; i <= n; i++) {
            cout << ans[i].fi << " 
    "[i == n];
        }
        for (int i = 1; i <= n; i++) {
            cout << ans[i].se << " 
    "[i == n];
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        init();
        run();
        return 0;
    }
    

    E. Two Arrays

    首先判掉不合法的情况,若对于(a_i=b_k)且此时(a_i)为最后一次出现,若(min{a_{i+1},cdots,a_n}<a_i),那么就不合法。注意开头(a_1,cdots,a_j,a_j)(b_1)的最后一次出现这段要特判。
    之后对于(1,...,m-1)每一个区间找到尽量靠左边的右端点,那么很容易得知右端点的取值范围,只要后面的取值合法就行,之后把所有的这些区间乘起来就行。
    上述过程可以二分、单调栈、模拟等多种方法解决。

    还有一种比较巧妙的做法,就是维护序列(a)的后缀,所有后缀最小值相等的区间天然形成了一段合法的移动区间,我们对于每个(b_i)把个数乘起来就行。注意一下判断不合法的情况,前面说的在实现过程中乘起来直接等于(0),不用特殊判断;但前面那一段无法确定,加上(suf_1 ot ={b_1})就行,这里大了小了都不满足条件。
    细节见代码:

    solution1
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/12 9:28:53
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5, MOD = 998244353;
     
    void run() {
        int n, m; cin >> n >> m;
        vector <int> a(n), b(m);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        for (int i = 0; i < m; i++) {
            cin >> b[i];
        }
        vector <int> r(m, -1);
        for (int i = n - 1, j = m - 1; i >= 0; i--) {
            if (j >= 0 && a[i] == b[j]) {
                r[j] = i;
                --j;
            }
        }
        if (r[0] == -1) {
            cout << 0 << '
    ';
            return;
        }
        r.push_back(n);
        for (int i = 0; i < r[0]; i++) {
            if (a[i] < b[0]) {
                cout << 0 << '
    ';
                return;
            }
        }
        for (int j = 0; j < m; j++) {
            for (int i = r[j] + 1; i < r[j + 1]; i++) {
                if (a[i] < b[j]) {
                    cout << 0 << '
    ';
                    return;
                }
            }
        }
        int ans = 1;
        for (int i = 0; i < m - 1; i++) {
            int j = r[i + 1];
            while (j > r[i] && a[j] >= b[i + 1]) {
                --j;
            }
            ans = 1ll * ans * (r[i + 1] - j) % MOD;
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
    solution2
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/12 10:09:52
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5, MOD = 998244353;
     
    void run() {
        int n, m; cin >> n >> m;
        vector <int> a(n), b(m);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        for (int i = 0; i < m; i++) {
            cin >> b[i];
        }
        vector <int> suf(n);
        suf[n - 1] = a[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            suf[i] = min(a[i], suf[i + 1]);
        }
        if (suf[0] != b[0]) {
            cout << 0 << '
    ';
            return;
        }
        map <int, int> mp;
        for (int i = 0; i < n; i++) {
            ++mp[suf[i]];
        }
        int ans = 1;
        for (int i = 1; i < m; i++) {
            ans = 1ll * ans * mp[b[i]] % MOD;
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    F. Jog Around The Graph

    题意:
    给定一个(n)个点,(m)条边的无向带权图。
    给定(q),问(1leq ileq q),从(1)出发经过(i)条边的最长路径为多少,记为(L(i)),可以经过重复的边。
    输出(displaystylesum_{i=1}^qL(i))
    (n,mleq 2000,qleq 10^9)

    思路:
    比较显然的一点是当(q)比较大时,我们显然的走法是在一条边上来回走。所以我们可以考虑分情况考虑:

    • (ileq m),我们可以直接暴力(dp)进行计算,类似于bellman-ford算法枚举边进行更新求最长路即可;
    • (i> m),显然后面的若干边反复横跳,主要处理这种情况。

    将式子写出来,记(f_i(e,k))为我们通过(k)条边到(e_u)或者(e_v),之后(i-k)条边反复横跳,那么:

    • (displaystyle f_i(e,k)=max(d[u][k],d[v][k])+(i-k)cdot w(e))

    显然一条边的贡献为(displaystyle f_i(e)=max_{k=1}^{n-1}{f_i(e,k)}),那么最终答案(ans_i=max_{e}f_i(e))
    那么现在处理(f_i(e,k)),我们可以写为:

    • (displaystyle f_i(e,k)=max(d[u][k],d[v][k])-kcdot w(e)+icdot w(e))

    可以看作一条直线,斜率为(w(e)),纵截距为(max(d[u][k],d[v][k])-kcdot w(e))。显然(f_i(e))只可能纵截距越大越优。
    所以现在每个(f_e(i))因为边不同为若干直线,对于每个(i)我们只用取最上端的即可。
    一般这种貌似求一个凸包就行,但这个题因为数据范围不是很大,我们可以直接暴力枚举,枚举每一条边在最上面所在的区间([l,r]),然后可以直接快速计算。
    假设现在枚举(i),考虑另外一个(j),现在有直线(y_i=w(i)cdot i+b_i,y_jw(j)cdot j+b_j),我们令(y_i>y_j)即可确定出一段区间。这个区间上下限会不断缩小,如果最终合法直接计算即可。
    细节见代码,主要是思路,这种线段取最优的题在图论中貌似还是挺常见的。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/17 18:34:51
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2000 + 5, MOD = 1e9 + 7;
     
    int n, m;
    ll q;
    int u[N], v[N], w[N];
     
    ll dp[2][N], b[N];
    int ans;
     
    void run() {
        cin >> n >> m >> q;
        for (int i = 1; i <= m; i++) {
            cin >> u[i] >> v[i] >> w[i];
        }
        memset(dp, -INF, sizeof(dp));
        memset(b, -INF, sizeof(b));
        dp[0][1] = 0;
        int ans = 0;
        for (int i = 1; i < n; i++) {
            for (int j = 1; j <= m; j++) {
                dp[i & 1][u[j]] = max(dp[i & 1][u[j]], dp[(i - 1) & 1][v[j]] + w[j]);
                dp[i & 1][v[j]] = max(dp[i & 1][v[j]], dp[(i - 1) & 1][u[j]] + w[j]);
            }
            for (int j = 1; j <= m; j++) {
                b[j] = max(b[j], max(dp[i & 1][u[j]], dp[i & 1][v[j]]) - 1ll * i * w[j]);
            }
            ans = (ans + *max_element(dp[i & 1] + 1, dp[i & 1] + n + 1)) % MOD;
        }
        for (int i = 1; i <= m; i++) {
            ll l = n, r = q;
            for (int j = 1; l <= r && j <= m; j++) if (i != j) {
                ll K = w[i] - w[j];
                ll B = b[j] - b[i];
                if (K > 0) {
                    l = max(l, B / K + 1);
                } else if (K < 0) {
                    r = min(r, B / K);
                } else {
                    if (!(B < 0 || (B == 0 && j > i))) {
                        r = -1;
                    }
                }
            }
            if (l <= r) {
                ans = ((ll)ans + (l + r) * (r - l + 1) / 2 % MOD * w[i] % MOD + b[i] * (r - l + 1) % MOD) % MOD;
                if (ans < 0) ans += MOD;
            }
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    G. Construct the String

    题意:
    给定(s,t)串。问最少删除几个字符使得(f(s)=t)
    (f)作用于(s)就类似于一个栈,依次考虑(s_i),若(s_i ot ={"."}),那么直接将(s_i)拼接在答案串后面;否则删除后面一个字符,没有就不删除。
    (n,mleq 10000)

    思路:
    显然这种题考虑(dp),因为(n,m)不算很大,并且时限比较宽松,所以可以考虑(O(nm))的做法,只要常数不太大就行。
    那么定义(dp[i][j])表示(s)匹配到了(i)(t)匹配到了(j)的最小删除个数。
    显然我们要考虑几种情况:

    • 直接匹配,向(dp[i+1][j+1])转移;
    • 删除(s_i),向(dp[i+1][j])转移;
    • 保留字符,可能会有两种情况,一种是向(dp[i+1][j])转移,另一种是向(dp[i+1][j-1])转移。

    第三种转移情况不好处理,因为我们可能会存在保留若干个,中间会删除某些,并且回退的情况,直接这样(dp)是无能为力的。
    注意我们保留字符时,这个字符最后是一定要被删掉的(否则就匹配,第一种考虑了),那么我们直接找到一个最近的位置满足这段刚好能被自己删除就行,也就是说我们往(dp[i+next[i]][j])转移。

    • 为什么直接往最近转移最优?因为后面的情况我们也能从(dp[i+next[i]][j])转移过去,所以一定不会差。
    • 为什么这样转移是正确的?考虑刚刚说的那种情况,要在中间删除一些,那么这种其实先删除(s_i)是等价的。这时我们像(dp[i+1][j])转移即可。

    所以第三种情况我们可以直接向(nxt[i])转移,并且能保证(dp)正确性。
    这个题感觉第三种情况的转换这里还是挺巧妙的,很多时候(dp)都要发现题目中隐含的信息,这样能够简化(dp)的转移。
    代码不难:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/18 10:42:35
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    
    void run() {
        string s, t;
        cin >> s >> t;
        int n = s.length(), m = t.length();
        vector <int> nxt(n, -1);
        for (int i = 0; i < n; i++) if (s[i] != '.') {
            int t = 0;
            for (int j = i; j < n; j++) {
                if (s[j] != '.') ++t;
                else --t;
                if (t == 0) {
                    nxt[i] = j;
                    break;
                }
            }
        }
        vector <vector <int>> dp(n + 1, vector <int>(m + 1, INF));
        dp[0][0] = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= m; j++) {
                //match
                if (j < m && s[i] == t[j]) {
                    dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][j]);
                }
                //skip
                dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + 1);
                //forward & back
                if (s[i] != '.' && nxt[i] != -1) {
                    dp[nxt[i] + 1][j] = min(dp[nxt[i] + 1][j], dp[i][j]);
                }
            }
        }
        cout << dp[n][m] << '
    ';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    Spring Boot 之Profile
    Spring Security初识
    Github使用进阶
    数据库JDBC
    Java内存模型(JMM)的可见性
    Spring Boot 整合Spring Data JPA
    Git版本控制工具初识
    Linux美化——终端提示符
    Python's Exception 层级结构
    试写Python内建函数range()
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/13099217.html
Copyright © 2020-2023  润新知