# 【牛客小白月赛70】A-F题解【小d和超级泡泡堂】【小d和孤独的区间】【小d的博弈】【小d和送外卖】

🎈 作者：Eriktse
🎈 简介：19岁，211计算机在读，现役ACM银牌选手🏆力争以通俗易懂的方式讲解算法！❤️欢迎关注我，一起交流C++/Python算法。（优质好文持续更新中……）🚀
🎈 阅读原文获得更好阅读体验：https://www.eriktse.com/algorithm/1109.html

## A - 小d和答案修改

Tag：签到

Code：

``````#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 9;

char s[N];

signed main()
{
cin >> s + 1;

for(int i = 1; s[i]; ++ i)
{
if('a' <= s[i] && s[i] <= 'z')printf("%c", s[i] - 'a' + 'A');
else printf("%c", s[i] - 'A' + 'a');
}

return 0;
}``````

## B - 小d和图片压缩

Tag：签到

Code：

``````#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e3 + 9;

int a[N][N];

signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;cin >> n >> m;
for(int i = 1;i <= n; ++ i)
for(int j = 1;j <= m; ++ j)
cin >> a[i][j];

for(int i = 1;i <= n; i += 2)
{
for(int j = 1;j <= m;j += 2)
{
int sum = a[i][j] + a[i + 1][j] + a[i][j + 1] + a[i + 1][j + 1];
cout << sum / 4 << ' ';
}
cout << '\n';
}

return 0;
}``````

## C - 小d和超级泡泡堂

Tag：dfs，联通块

Code:

``````#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e3 + 9;
char mp[N][N];

bitset<N> vis[N];

int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int n, m;

int dfs(int x, int y)
{
int res = mp[x][y] == '!';
for(int i = 0;i < 4; ++ i)
{
int nx = x + dx[i], ny = y + dy[i];
if(nx < 1 || nx > n || ny < 1 || ny > m || vis[nx][ny] || mp[nx][ny] == '#')continue;
vis[nx][ny] = true;
res += dfs(nx, ny);
}
return res;
}

signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1;i <= n; ++ i)cin >> mp[i] + 1;
int sx, sy;
for(int i = 1;i <= n; ++ i)
for(int j = 1;j <= m; ++ j)if(mp[i][j] == '@')sx = i, sy = j;

int ans = dfs(sx, sy);
cout << ans << '\n';
return 0;
}``````

## D - 小d和孤独的区间

Tag：思维，dp，组合计数

Code:

``````#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 9;
int a[N], l[N], r[N];

signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;cin >> n;
for(int i = 1;i <= n; ++ i)cin >> a[i];
for(int i = 1;i <= n; ++ i)
{
if(a[i] == 1)continue;
if(i > 1 && a[i - 1] == 0)l[i] = l[i - 1] + 1;
else l[i] = 1;
}
for(int i = n;i >= 1; -- i)
{
if(a[i] == 1)continue;
if(i < n && a[i + 1] == 0)r[i] = r[i + 1] + 1;
else r[i] = 1;
}
int ans = 0;
for(int i = 1;i <= n; ++ i)
{
if(a[i] == 1)ans += (l[i - 1] + 1) * (r[i + 1] + 1);
}
cout << ans << '\n';
return 0;
}``````

## E - 小d的博弈

Tag：博弈，思维

W必胜态: 当`n > 2m || m > 2n`时，我们可以通过切分使得对手得到一个正方形，所以此时是必胜的。

Code:

``````#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 9;

void solve()
{
int n, m;cin >> n >> m;
int ans = 1;
while(1)
{
if(n > 2 * m || m > 2 * n)break;

if(n > m)n = (n - 1) / 2;
else m = (m - 1) / 2;
ans ^= 1;
}
cout << (ans ? "Alice" : "Bob") << '\n';
}

signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _;cin >> _;
while(_ --)solve();
return 0;
}``````

## F - 小d和送外卖

Tag：树形dp，背包，图论

`dp[x][i]`表示在以节点`x`为根的子树上删除`i`个点后可以减少的最大路程。

`s[x]`表示在以节点`x`为根的子树中的需求量（标记为`need`的点的个数）。

Code：

``````#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 9;
int dp[N][60], s[N];//dp[i][j]表示在i为根的子树中删除j个点的最大贡献
//s[i]表示以i为根的子树中的需求量
vector<int> g[N];
bitset<N> need;
int tot, n, m;;
void dfs(int x, int p)
{
s[x] = need[x];
for(auto &y : g[x])
{
if(y == p)continue;
dfs(y, x);
if(s[y] == 0)continue;

static int f[60];
memset(f, 0, sizeof f);
for(int k = 0;k <= min(m, s[x] + s[y]); ++ k)
{
//x树中取i个，注意此时x树并不完整
//在y中取k - i个，此时y树为完整的
for(int i = 0;i <= min(m, s[x]); ++ i)
{
if(k - i <= s[y] && k - i >= 0)
f[k] = max(f[k], dp[x][i] + dp[y][k - i] + (k - i == s[y] ? 2 : 0));
}
}
s[x] += s[y];
tot += 2;//此时已经保证s[y] != 0，注意看上面的continue
for(int i = 0;i <= min(m, s[x] + s[y]); ++ i)dp[x][i] = f[i];
}
}

signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1;i < n; ++ i)
{
int x, y;cin >> x >> y;
g[x].push_back(y), g[y].push_back(x);
}

int k;cin >> k;
for(int i = 1;i <= k; ++ i)
{
int x;cin >> x;
need[x] = true;
}

dfs(1, -1);
cout << tot - dp[1][m] << '\n';
return 0;
}``````
🎈 本文由eriktse原创，创作不易，如果对您有帮助，欢迎小伙伴们点赞👍、收藏⭐、留言💬

##### Eriktse
4 声望0 粉丝

19岁，性别未知，ACM-ICPC现役选手，ICPC亚洲区域赛银牌摆烂人，CCPC某省赛铜牌蒟蒻，武汉某院校计算机科学与技术专业本科在读。

0 条评论