牛客周赛 Round 88
A. 吔我大炮!
点击查看代码
void solve() {
int a, b, c;
std::cin >> a >> b >> c;
if (a * b <= c) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
}
B. 梦间
题意:判断三角形有没有一条中线是坐标轴。
枚举两个点求出中点然后和另一个点判断是不是在坐标轴上。
点击查看代码
void solve() {
std::pair<int, int> a[3];
for (int i = 0; i < 3; ++ i) {
std::cin >> a[i].first >> a[i].second;
}
for (int i = 0; i < 3; ++ i) {
for (int j = i + 1; j < 3; ++ j) {
int k = 0;
while (k == i || k == j) {
++ k;
}
int x = (a[i].first + a[j].first) * 10 / 2, y = (a[i].second + a[j].second) * 10 / 2;
if ((x == 0 && a[k].first == 0) || (y == 0 && a[k].second == 0)) {
std::cout << "Yes\n";
return;
}
}
}
std::cout << "No\n";
}
C. 坠入
题意:和\(B\)差不多,不管是问有没有和坐标轴平行。
判断中点和另一个点的线段是不是和坐标轴平行。
点击查看代码
void solve() {
std::pair<int, int> a[3];
for (int i = 0; i < 3; ++ i) {
std::cin >> a[i].first >> a[i].second;
}
for (int i = 0; i < 3; ++ i) {
for (int j = i + 1; j < 3; ++ j) {
int k = 0;
while (k == i || k == j) {
++ k;
}
int x = (a[i].first + a[j].first) * 10 / 2, y = (a[i].second + a[j].second) * 10 / 2;
if ((x == a[k].first * 10) || (y == a[k].second * 10)) {
std::cout << "Yes\n";
return;
}
}
}
std::cout << "No\n";
}
D. 漫步
题意:给你一个\(x\),求一个\(z, 1\leq z < x\),使得\(x | (x + z) = x + z\)。\(|\)是或运算。
找到不高于\(x\)最高位1的\(x\)是零的那一位。
点击查看代码
void solve() {
i64 x;
std::cin >> x;
bool flag = false;
for (int i = 60; i >= 0; -- i) {
if (x >> i & 1) {
flag = true;
} else if (flag) {
std::cout << (1ll << i) << "\n";
return;
}
}
std::cout << -1 << "\n";
}
E. 秘藏
题意:一个\(a \times n\)的数组,你从\((1, 1)\)开始,要到\((1, n)\)或者\((2, n)\)。每个格子有价值。每次从当前行到下一列不花费价值,跳到另一行花费\(k\)的价值。求最大价值。
记\(f[0/1][i]\)为到第0/1行\(i\)列的最大价值,那么\(f[j][i + 1] = \max(f[j][i + 1], f[j][i] + a[j][i + 1])\),如果\(f[j][i] \geq k\)那么,\(f[j \oplus1][i + 1] = \max(f[j \oplus 1][i + 1], f[j][i] + a[j \oplus 1][i + 1] - k)\)。
点击查看代码
void solve() {
int n, k;
std::cin >> n >> k;
std::vector a(2, std::vector<i64>(n));
for (int i = 0; i < 2; ++ i) {
for (int j = 0; j < n; ++ j) {
std::cin >> a[i][j];
}
}
const i64 inf = 1e18;
std::vector f(2, std::vector<i64>(n, -inf));
f[0][0] = a[0][0];
for (int i = 0; i + 1 < n; ++ i) {
for (int j = 0; j < 2; ++ j) {
f[j][i + 1] = std::max(f[j][i + 1], f[j][i] + a[j][i + 1]);
if (f[j][i] >= k) {
f[j ^ 1][i + 1] = std::max(f[j ^ 1][i + 1], f[j][i] + a[j ^ 1][i + 1] - k);
}
}
}
std::cout << std::max(f[0][n - 1], f[1][n - 1]) << "\n";
}
F. 回响
题意:一个数组,有些地方已经有数了,有些没数,你要把他们填上。使得相邻两个数正好相差\(1\)。
考虑那些最靠近的两个非零数,我们只需要在他们中间填。如果\(|a_i - a_j| = j - i\),那么直接看大小关系顺序填就行。
否则如果\(a_i \leq a_j\),我们就\(a_i + 1, a_i + 2..\)这样填,一直到\(a_k - a_j = j - k\)就可以递减填。\(a_i > a_j\)同样的考虑方式。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
bool flag = false;
for (int i = 0; i < n; ++ i) {
if (a[i] != 0) {
if (!flag) {
for (int k = i - 1; k >= 0; -- k) {
a[k] = a[k + 1] + 1;
}
flag = true;
}
int j = i + 1;
while (j < n && a[j] == 0) {
++ j;
}
if (j == n - 1) {
for (int k = j + 1; k < n; ++ k) {
a[k] = a[k - 1] + 1;
}
}
if (a[i] < a[j]) {
if (j - i == a[j] - a[i]) {
for (int k = i + 1; k < j; ++ k) {
a[k] = a[k - 1] + 1;
}
} else {
for (int k = i + 1; k < j; ++ k) {
a[k] = a[k - 1] + 1;
if (a[k] - a[j] == j - k) {
for (int l = k + 1; l < j; ++ l) {
a[l] = a[l - 1] - 1;
}
break;
}
}
}
} else {
if (j - i == a[i] - a[j]) {
for (int k = i + 1; k < j; ++ k) {
a[k] = a[k - 1] - 1;
}
} else {
for (int k = i + 1; k < j; ++ k) {
a[k] = a[k - 1] - 1;
if (a[j] - a[k] == j - k) {
for (int l = k + 1; l < j; ++ l) {
a[l] = a[l - 1] + 1;
}
break;
}
}
}
}
i = j - 1;
}
}
for (int i = 1; i < n; ++ i) {
if (std::abs(a[i] - a[i - 1]) != 1) {
std::cout << -1 << "\n";
return;
}
}
for (int i = 0; i < n; ++ i) {
std::cout << a[i] << " \n"[i == n - 1];
}
}
G. 升!龙!
题意:给你一棵树,一棵树的价值为每个叶子节点到根的路径和的最大值。现在每次把一个子树移动到一个节点下面,求价值。
我们可以把每个节点子树的叶子节点的值存下来,因为非叶子节点乘叶子节点的数量不会很大。
那么\(dfs\)求出每个点从上往下的路径最大值和从下往上的路径最大值。并用一个\(multiset\)存每个叶子的值,那么把\(x\)接到\(y\)我们可以把\(x\)这棵子树的叶子的值都删掉,然后把\(x\)父亲到根的和加进来,再把子树的从下往上的最大值加上\(y\)从从上往下的值的和加加进来,此时set里的最大值就是答案。最后还原之前的set就行。
点击查看代码
void solve() {
int n, q;
std::cin >> n >> q;
std::vector<i64> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::vector<std::vector<int>> adj(n);
std::vector<i64> sum(n), sub(n), fa(n);
for (int i = 1; i < n; ++ i) {
std::cin >> fa[i];
-- fa[i];
adj[fa[i]].push_back(i);
}
std::vector<std::vector<i64>> b(n);
std::multiset<i64> s;
auto dfs = [&](auto & self, int u) -> void {
for (auto & v : adj[u]) {
sum[v] = a[v] + sum[u];
self(self, v);
sub[u] = std::max(sub[u], sub[v] + a[u]);
for (auto & x : b[v]) {
b[u].push_back(x);
}
}
if (adj[u].empty()) {
sub[u] = a[u];
s.insert(sum[u]);
b[u].push_back(sum[u]);
}
};
fa[0] = -1;
sum[0] = a[0];
dfs(dfs, 0);
while (q -- ) {
int x, y;
std::cin >> x >> y;
-- x, -- y;
for (auto & v : b[x]) {
s.extract(v);
}
s.insert(sum[fa[x]]);
s.insert(sub[x] + sum[y]);
std::cout << *s.rbegin() << "\n";
s.extract(sub[x] + sum[y]);
s.extract(sum[fa[x]]);
for (auto & v : b[x]) {
s.insert(v);
}
}
}

浙公网安备 33010602011771号