其他分享
首页 > 其他分享> > Codeforces Round #635 (Div. 1)

Codeforces Round #635 (Div. 1)

作者:互联网

传送门

A. Linova and Kingdom

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

思路:

因为一个点选择了所有子树也会被选,并且显然子树的\(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 << '\n';
}
 
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 << '\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;
}

C. Kaavi and Magic Spell

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

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

思路:
将\(T\)串用\(*\)补齐到与\(S\)长度相同,问题转化为了对于\(T\)的一个前缀,\(S\)有多少种匹配方法。
注意到有个性质:匹配任意一段\(T\)时,我们只会用到\(S\)的一个前缀。
那么我们直接跑个区间\(dp\),表示匹配\(T[l,r]\)的方案数,转移时直接根据\(s[r-l+1]\)\(O(1)\)转移即可。
最后答案即为\(\sum_{i\geq 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 << '\n';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

标签:635,int,void,args,cout,Codeforces,Div,include,define
来源: https://www.cnblogs.com/heyuhhh/p/12710644.html