zoukankan      html  css  js  c++  java
  • Codeforces Round #646 (Div. 2)

    传送门

    视频题解

    A. Odd Selection

    注意到(nleq 1000),所以直接暴力枚举即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/31 22:35:54
     */
    #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, x; cin >> n >> x;
        vector <int> a(n);
        int cnt[2] = {0, 0};
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            if (a[i] & 1) ++cnt[1];
            else ++cnt[0];
        }
        for (int i = 1; i <= x; i += 2) {
            if (cnt[1] >= i && cnt[0] >= x - i) {
                cout << "YES" << '
    ';
                return;
            }
        }
        cout << "NO" << '
    ';
    }
     
    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. Subsequence Hate

    最后的形式一定为(000...111,111...000,1111..11,00..00)这几种形式,所以只用考虑这几种情况就行。前两种枚举一下即可解决,后两种也很简单。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/31 22:42:37
     */
    #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; cin >> s;
        int n = s.length();
        int ans = INF;
        vector <int> sum(n);
        for (int i = 0; i < n; i++) {
            if (i == 0) sum[0] = (s[i] == '1');
            else sum[i] = sum[i - 1] + (s[i] == '1');    
        }
        int cnt0 = 0, cnt1 = 0;
        for (int i = n - 1; i; i--) {
            if (s[i] == '0') {
                ++cnt0;
            } else {
                ++cnt1;
            }
            ans = min(ans, min(sum[i - 1], i - sum[i - 1]) + min(cnt0, cnt1));
        }
        ans = min(ans, min(sum[n - 1], n - sum[n - 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;
    }
    

    C. Game On Leaves

    首先(x)为叶子结点(注意(n=1)的情况)必胜。
    否则最后必胜态为如下形式:

    具体证明可参见题解或者视频里所说的。
    容易发现最终答案只与结点个数的奇偶性有关,所以判断一下就行。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/31 23:06:05
     */
    #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, x; cin >> n >> x; --x;
        vector <int> d(n);
        for (int i = 1; i < n; i++) {
            int u, v; cin >> u >> v;
            --u, --v;
            ++d[u], ++d[v];
        }
        if (d[x] <= 1) {
            cout << "Ayush" << '
    ';
            return;   
        }
        if (n & 1) cout << "Ashish" << '
    ';
        else cout << "Ayush" << '
    ';
    }
     
    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. Guess The Maximums

    交互题。
    存在一种刚好用(12)次的方法,具体方法可以看看视频题解,注意第一次询问我们直接对两个集合进行询问,同样能找到最大值,并且还可以在分治的时候省略一层。
    细节见代码:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/31 23:56:07
     */
    #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>
    #include <random>
    #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;
    mt19937 rnd(time(NULL));
     
    int n, k;
     
    int query2(vector <int>& a) {
        cout << "? " << sz(a) << '
    ';
        for (auto it : a) cout << it << ' ';
        cout << endl;
        int x; cin >> x;
        return x;   
    }
     
    int query(vector <int> a) {
        sort(all(a));
        vector <int> b;
        int j = 0;
        for (int i = 1; i <= n; i++) {
            if (j >= sz(a) || i != a[j]) {
                b.push_back(i);
            } else ++j;
        }
        return query2(b);
    }
     
    void run() {
        cin >> n >> k;
        vector <int> ans(k);
        vector <vector<int>> s(k);
        for (int i = 0; i < k; i++) {
            int c; cin >> c;
            s[i].resize(c);
            for (int j = 0; j < c; j++) {
                cin >> s[i][j];
            }
            sort(all(s[i]));
        }
        int Max;
        int m = (k - 1) / 2;
        vector <int> a, b;
        for (int i = 0; i <= m; i++) {
            for (auto it : s[i]) {
                a.push_back(it);
            }   
        }
        for (int i = m + 1; i < k; i++) {
            for (auto it : s[i]) {
                b.push_back(it);
            }
        }
        int Max1 = query(a), Max2 = query(b);
        Max = max(Max1, Max2);
        if (Max1 == Max2) {
            for (int i = 0; i < k; i++) {
                ans[i] = Max1;
            }
        } else {
            function <int(int, int)> solve;
            solve = [&] (int l, int r) -> int {
                if (l == r) return l;
                int m = (l + r) >> 1;
                vector <int> a;
                for (int i = l; i <= m; i++) {
                    for (auto it : s[i]) {
                        a.push_back(it);
                    }
                }
                int now = query(a);
                if (now == Max) return solve(m + 1, r);
                return solve(l, m);
            };
            int t;
            if (Max1 < Max2) t = solve(0, m);
            else t = solve(m + 1, k - 1);
            for (int i = 0; i < k; i++) {
                if (i != t) ans[i] = Max;
                else ans[i] = query(s[i]);
            }              
        }
        cout << "!";
        for (auto it : ans) cout << ' ' << it;
        cout << endl;
        string ok; cin >> ok;
        if (ok != "Correct") exit(0);
    }
     
    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;
    }
    

    E. Tree Shuffling

    注意到(a[u]=min(a[u],a[fa[u]])),那么执行完这个操作过后问题将变为一个子树内的问题,与父亲结点无关。
    在一个子数内的话直接贪心将儿子结点剩余进行匹配即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/31 23:20:34
     */
    #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 = 2e5 + 5;
     
    int n;
    vector <int> G[N];
    int a[N], b[N], c[N];
    int cnt[N][2];
    ll ans;
     
    void dfs(int u, int fa) {
        if (fa) a[u] = min(a[u], a[fa]);
        int f = -1;
        if (b[u] == 0 && c[u]) f = 0;
        if (b[u] && c[u] == 0) f = 1;
        int c0 = 0, c1 = 0;
        for (auto v : G[u]) if (v != fa) {
            dfs(v, u);
            cnt[u][0] += cnt[v][0];
            cnt[u][1] += cnt[v][1];
            if (cnt[v][0] > cnt[v][1]) c0 += cnt[v][0] - cnt[v][1];
            else c1 += cnt[v][1] - cnt[v][0];
        }
        if (f == 0) ++cnt[u][0], ++c0;
        if (f == 1) ++cnt[u][1], ++c1;
        ans += 2ll * a[u] * min(c0, c1);
    }
     
    void run() {
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i] >> b[i] >> c[i];
        }
        for (int i = 1; i < n; i++) {
            int u, v; cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1, 0);
        if (cnt[1][0] != cnt[1][1]) ans = -1;
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    F. Rotating Substrings

    很神仙的dp,不好想。
    有两种做法,第一种做法可以参见视频题解里面说的,我们要求一个最长的公共子序列,并且剩下的每一个在(s)串中没有匹配的数都只能往前移动。
    那么即是对每一个匹配的(s_i,t_j),(i+1 ightarrow n)(x)字符出现的次数不小于(t+1 ightarrow n)中出现的次数,这样的话最终剩下没有匹配的只能往右边走。那么最终答案即为(n-dp[n][n])
    另外一种做法也很神奇!我们定义(dp[i][j])(s)串中确定了(i)个字符,(t)串匹配到了(j)时,最少需要插入的数的个数,显然最终答案即为(dp[n][n])
    那么我们将题目中的操作看作两部分,一部分是选出一些数准备插入,另外一部分就是插入。
    那么往后移动(j)时其实我们在不断选择一些数出来,然后往后移动(i)时我们在不断插入一些数,代价为(1),当然如果(s[i]=t[j])的话就不用消耗代价。
    细节见代码吧。。

    solution1
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/1 13:32:17
     */
    #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;
    
    void run() {
        int n; cin >> n;
        string s, t; cin >> s >> t;
        string ss = s, tt = t;
        sort(all(ss)), sort(all(tt));
        if (ss != tt) {
            cout << -1 << '
    ';
            return;
        }
        s = '#' + s;
        t = '#' + t;
        vector <vector <int>> dp(n + 1, vector<int>(n + 1));
        vector <vector <int>> suf_s(n + 2, vector<int>(26)), suf_t(n + 2, vector<int>(26));
        for (int i = n; i >= 1; i--) {
            for (int j = 0; j < 26; j++) {
                suf_s[i][j] = suf_s[i + 1][j];
                suf_t[i][j] = suf_t[i + 1][j];
            }
            ++suf_s[i][s[i] - 'a'];
            ++suf_t[i][t[i] - 'a'];
        }
        dp[0][0] = 0;
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= n; j++) {
                if (i) dp[i][j] = dp[i - 1][j];
                if (j) dp[i][j] = max(dp[i][j], dp[i][j - 1]);
                if (i && j && s[i] == t[j]) {
                    bool ok = true;
                    for (int k = 0; k < 26; k++) {
                        if (suf_s[i][k] < suf_t[j][k]) ok = false;   
                    }
                    if (ok) {
                        dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);   
                    }
                }
            }   
        }
        cout << n - dp[n][n] << '
    ';
    }
    
    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;
    }
    
    solution1
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/1 21:01:21
     */
    #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; cin >> n;
        string s, t; cin >> s >> t;
        string ss = s, tt = t;
        sort(all(ss)), sort(all(tt));
        if (ss != tt) {
            cout << -1 << '
    ';
            return;
        }
        s = '#' + s;
        t = '#' + t;
        vector <vector <int>> dp(n + 1, vector<int>(n + 1, INF));   
        vector <vector <int>> suf_s(n + 2, vector<int>(26)), suf_t(n + 2, vector<int>(26));
        for (int i = n; i >= 1; i--) {
            for (int j = 0; j < 26; j++) {
                suf_s[i][j] = suf_s[i + 1][j];
                suf_t[i][j] = suf_t[i + 1][j];
            }
            ++suf_s[i][s[i] - 'a'];
            ++suf_t[i][t[i] - 'a'];
        }
        for (int i = 0; i <= n; i++) {
            dp[0][i] = 0;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = i; j <= n; j++) {
                if (s[i] == t[j]) {
                    dp[i][j] = dp[i - 1][j - 1];
                }
                dp[i][j] = min(dp[i][j], dp[i - 1][j] + 1);
                if (suf_s[i + 1][t[j] - 'a'] > suf_t[j + 1][t[j] - 'a']) {
                    dp[i][j] = min(dp[i][j], dp[i][j - 1]);
                }
            }
        }
        cout << dp[n][n] << '
    ';
    }
    
    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;
    }
    
  • 相关阅读:
    每日算法
    每日算法
    搜索算法入门详解
    NLP
    每日算法
    每日算法
    Elasticsearch地理位置总结
    elasticsearch Geo Bounding Box Query
    elasticsearch Geo Distance Query
    Elasticsearch java API (23)查询 DSL Geo查询
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/13027492.html
Copyright © 2011-2022 走看看