$CF 635 (Div 2)$

(CF 635 (Div2))

(A.)

给定 (a, b, c, d),构造 (x, y, z) 满足 (aleq xleq bleq yleq cleq zleq d),且 (x, y, z) 能构成三角形

贪心,(x = b, y = z = c)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " 
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9 + 7;
const int N = 2e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
int t, n, a[N];
 
inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}
 
int main()
{
    t = read();
    while(t--) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        printf("%d %d %d
", b, c, c);
    }
    return 0;
}

(B.)

给定一个 (x),对 (x) 可以进行两个操作

  • (x) 变为 (leftlfloorfrac{x}{2} ight floor + 10)
  • (x) 变为 (x - 10)

(1) 个操作最多用 (n) 次,第 (2) 个操作最多用 (m)

询问是否可以在有限次数内让 (x) 小于等于 (0)

一个显然的 (observation) 是,不能一直用操作 (1),那样会导致 (x) 不降反升

暴力跑循环,如果当前 (x) 可以被剩下的 (m) 次操作 (2) 完结,那么就可以成功;其他情况都无法成功

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " 
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9 + 7;
const int N = 1e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
int t, x, n, m;
 
inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}
 
int main()
{
    t = read();
    while(t--) {
        x = read(), n = read(), m = read();
        int f = 0;
        while(1) {
            if(x <= m * 10) {f = 1; break;}
            else {
                if(n) x = x / 2 + 10, n--;
                else break;
            }
        }
        if(!f) puts("NO");
        else puts("YES");
    }
    return 0;
}

(C.)

给定一棵 (n) 个节点的无根树,选定 (1) 为根

任选 (k) 个节点作为工业区,剩下的 (n - k) 个节点作为旅游区,每个工业区节点派一个大使,定义一个大使的 (happiness) 为其前往点 (1) 的最短路上经过的旅游区的数量

求所有大使 (happiness) 和的最大值

对于 (i) 节点,定义 (dep[i])(i) 的深度,(sub[i])(i) 子节点的个数

考虑每个节点 (i) 对答案的贡献

(1.) 如果 (i) 是叶子,贡献即为 (dep[i] = dep[i] - 0)
(2.) 如果 (i) 是根,贡献即为 (dep[i] - sub[i])

(2) 点的简易正确性证明:

考虑 (i) 为根节点

若当前选定 (i),那么在 (i) 被选取之前,其所有子节点都已经被选取,否则可以选取他的子节点,那样的话深度更大,子节点个数更小,对答案贡献更大

(dfs) 预处理深度和子节点个数,然后对 (dep[i] - sub[i]) 排序取前 (k) 个和即可

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " 
"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9 + 7;
const int N = 2e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;

inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}

int t, n, k;
vector<int> g[N];
int a[N], dep[N], sub[N];
void dfs(int u, int v)
{
    for(auto i: g[u]) {
        if(i != v) {
            dep[i] = dep[u] + 1;
            dfs(i, u);
            sub[u] += 1 + sub[i];
        }
    }
}
int main()
{
    n = read(), k = read();
    for(int i = 1; i < n; ++i) {
        int a, b;
        a = read(), b = read();
        g[a].push_back(b), g[b].push_back(a);
    }
    dfs(1, 0);
    for(int i = 1; i <= n; ++i)
        a[i] = dep[i] - sub[i];
    sort(a + 1, a + 1 + n);
    reverse(a + 1, a + 1 + n);
    LL ans = 0;
    for(int i = 1; i <= k; ++i)
        ans += 1LL * a[i];
    printf("%lld
", ans);
    return 0;
}

对于无根树,任意一个节点都可以作为根,无需讨论

原文地址:https://www.cnblogs.com/ChenyangXu/p/12710852.html