$CF\ 635\ (Div\ 2)$
\(CF\ 635\ (Div2)\)
\(A.\)
给定 \(a,\ b,\ c,\ d\),构造 \(x,\ y,\ z\) 满足 \(a\leq x\leq b\leq y\leq c\leq z\leq 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], " \n"[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\n", b, c, c);
}
return 0;
}
\(B.\)
给定一个 \(x\),对 \(x\) 可以进行两个操作
- \(x\) 变为 \(\left\lfloor\frac{x}{2}\right\rfloor + 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], " \n"[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], " \n"[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\n", ans);
return 0;
}
对于无根树,任意一个节点都可以作为根,无需讨论