• Codeforces Round #635 (Div. 1)


    传送门

    A. Linova and Kingdom

    题意:
    给定一颗以(1)为根的树,现在要选定(k)个结点为黑点,一个黑点的贡献为从他出发到根节点经过的白点数量。
    问黑点贡献总和最大为多少。

    思路:

    • 最直接的想法黑点肯定是位于深度越深的点越好,并且有这样一个性质:假设我们选择了一个点,那么该点的所有后代也将会被选择。
    • 一个黑点产生的贡献为其深度减去到根路径中黑点的数量。
    • 直接按照上述思路贪心不好思考,考虑转化一下贡献的计算方法:我们减去黑点的数量时在其祖先结点再减。也就是说每个黑点会减去其子树(size)
    • 那么对于所有点按照(deep-size)进行排序,从大到小贪心选即可。

    因为一个点选择了所有子树也会被选,并且显然子树的(deep-size)更大,所以容易证明这种贪心是正确的。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/4/15 22:36:55
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #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, k;
    vector <int> G[N];
    int d[N], sz[N];
     
    void dfs(int u, int fa) {
        d[u] = d[fa] + 1;
        sz[u] = 1;
        for(auto v : G[u]) if(v != fa) {
            dfs(v, u);
            sz[u] += sz[v];
        }   
    }
     
    void run() {
        cin >> n >> k;
        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);
        vector <int> v;
        for(int i = 1; i <= n; i++) {
            v.push_back(d[i] - sz[i]);   
        }
        sort(all(v));
        reverse(all(v));
        ll ans = 0;
        for(int i = 0; i < k; i++) ans += v[i];
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    B. Xenia and Colorful Gems

    枚举一维,然后另外两维直接贪心二分即可。
    代码写得有点乱。。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/4/15 22:47:16
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #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;
     
    int na, nb, nc;
     
    ll a[N], b[N], c[N];
     
    ll calc(int x, int y, int z) {
        if(x && y && z && x <= na && y <= nb && z <= nc)
            return (a[x] - b[y]) * (a[x] - b[y]) + (a[x] - c[z]) * (a[x] - c[z]) + (b[y] - c[z]) * (b[y] - c[z]);
        return 8e18;
    }
     
    ll calc_a(int y, int z) {
        int t = lower_bound(a + 1, a + na + 1, b[y]) - a;
        ll res = 9e18;
        res = min(res, calc(t, y, z));
        res = min(res, calc(t - 1, y, z));
        t = lower_bound(a + 1, a + na + 1, c[z]) - a;
        res = min(res, calc(t, y, z));
        res = min(res, calc(t - 1, y, z));
        return res;
    }
     
    ll calc_c(int x, int y) {
        int t = lower_bound(c + 1, c + nc + 1, b[y]) - c;
        ll res = 9e18;
        res = min(res, calc(x, y, t));
        dbg(x, y, t, res);
        res = min(res, calc(x, y, t - 1));
        t = lower_bound(c + 1, c + nc + 1, a[x]) - c;
        res = min(res, calc(x, y, t));
        res = min(res, calc(x, y, t - 1));
        return res;
    }
     
    ll calc_b(int x, int z) {
        int t = lower_bound(b + 1, b + nb + 1, c[z]) - b;
        ll res = 9e18;
        res = min(res, calc(x, t, z));
        res = min(res, calc(x, t - 1, z));
        t = lower_bound(b + 1, b + nb + 1, a[x]) - b;
        res = min(res, calc(x, t, z));
        res = min(res, calc(x, t - 1, z));
        return res;   
    }
     
    void run() {
        cin >> na >> nb >> nc;
        for(int i = 1; i <= na; i++) cin >> a[i];
        for(int i = 1; i <= nb; i++) cin >> b[i];
        for(int i = 1; i <= nc; i++) cin >> c[i];
        sort(a + 1, a + na + 1);
        sort(b + 1, b + nb + 1);
        sort(c + 1, c + nc + 1);
        ll ans = 9e18;
        for(int i = 1, t; i <= na; i++) {
            t = lower_bound(b + 1, b + nb + 1, a[i]) - b;
            if(t <= nb) ans = min(ans, calc_c(i, t));
            if(t > 1) ans = min(ans, calc_c(i, t - 1));
            t = lower_bound(c + 1, c + nc + 1, a[i]) - c;
            if(t <= nc) ans = min(ans, calc_b(i, t));
            if(t > 1) ans = min(ans, calc_b(i, t - 1));
        }
        for(int i = 1, t; i <= nb; i++) {
            t = lower_bound(a + 1, a + na + 1, b[i]) - a;
            ans = min(ans, calc_c(t, i));
            ans = min(ans, calc_c(t - 1, i));
            t = lower_bound(c + 1, c + nc + 1, b[i]) - c;
            ans = min(ans, calc_a(i, t));
            ans = min(ans, calc_a(i, t - 1));
        }
        for(int i = 1, t; i <= nc; i++) {
            t = lower_bound(b + 1, b + nb + 1, c[i]) - b;
            ans = min(ans, calc_a(t, i));
            ans = min(ans, calc_c(t - 1, i));
            t = lower_bound(a + 1, a + na + 1, c[i]) - a;
            ans = min(ans, calc_b(t, i));
            ans = min(ans, calc_b(t - 1, i));
        }
        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. Kaavi and Magic Spell

    题意:
    给出串(S,T),现在有一个空串(A),然后每次执行以下操作:

    • 选择(S)的第一个字符并删除,然后将其插入(A)的前面或者后面。

    现在问有多少种方式使得串(T)为串(A)的前缀。

    思路:
    (T)串用(*)补齐到与(S)长度相同,问题转化为了对于(T)的一个前缀,(S)有多少种匹配方法。
    注意到有个性质:匹配任意一段(T)时,我们只会用到(S)的一个前缀。
    那么我们直接跑个区间(dp),表示匹配(T[l,r])的方案数,转移时直接根据(s[r-l+1])(O(1))转移即可。
    最后答案即为(sum_{igeq m}{dp_{1,i}})
    细节见代码:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/4/16 9:06:01
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #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 = 3000 + 5, MOD = 998244353;
     
    int n, m;
    char s[N], t[N];
    int dp[N][N];
     
    int solve(int l, int r) {
        if(l > r) return 1;
        if(dp[l][r] != -1) return dp[l][r];
        int k = r - l + 1;
        int res = 0;
        if(l > m || s[k] == t[l]) res += solve(l + 1, r);
        if(r > m || s[k] == t[r]) res = (res + solve(l, r - 1)) % MOD;
        return dp[l][r] = res;
    }
     
    void run() {
        cin >> (s + 1) >> (t + 1);
        n = strlen(s + 1), m = strlen(t + 1);
        memset(dp, -1, sizeof(dp));
        int ans = 0;
        for(int i = m; i <= n; i++) {
            ans = (ans + solve(1, i)) % MOD;   
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    Linux文件权限学习总结
    【转】Hibernate和ibatis的比较
    Spring AOP原理及拦截器
    Spring AOP (下)
    Spring AOP (上)
    SQL语句限定查询知识点总结
    多线程知识点总结
    关于tomcat那些事情
    java.lang.NoClassDefFoundError: org/apache/commons/codec/DecoderException 的解决办法
    cacti 与 nagios 一些总结 【八】
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12710644.html
Copyright © 2020-2023  润新知