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

比赛传送门:https://ac.nowcoder.com/acm/contest/53366

难度适中。

🎈 作者: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,联通块

给定一个大小为n x m的地图,求起点@所在的联通块的大小。

用深度优先搜索dfs扫一遍即可,复杂度O(nm),当然你想用bfs也行。

注意不要越界。

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,组合计数

给定一个长度为0的01串,问有多少个子串是仅包含一个1的。

我们可以求两个数组,l[i]表示从i点开始,往左有多少个连续的0,r[i]表示从i点开始,往右有多少连续的0。

然后我们枚举每一个点,如果发现a[i] == 1,说明这个点i可以被一些区间包含到且仅有这一个1,那么是哪些区间呢?我们假设这个区间为[s, e],那么一定有s <= i && i <= e,且[s, i - 1]中只包含0,[i + 1, e]中只包含0。

那么我们可以得到左端点s的取值有l[i - 1] + 1种,右端点e的取值有r[i + 1] + 1种。

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:博弈,思维

给定一个大小为n x m的矩形,Alice和Bob轮流对其进行操作,每次操作可以横着或竖着在把矩形切一刀分成两个长宽都为整数的矩形,然后留下面积较小的那个,两个矩形面积相等是不被允许的,也就是说不能从中间切。

当无法继续操作的时候就输了。

我们分析一下容易发现几种必败的局面,(1, 1), (1, 2), (2, 1), (2, 2)无法操作,直接败。

通过分析一些特殊的矩形,比如n=m的情况,我们可以发现n=m的时候也是必败的,因为下一个人一定可以模仿当前操作者的操作,从而每次都使得回到自己手上的都是一个正方形,那么最终必然会到(1, 1)或(2, 2)的必败局面。

所以我们思考,当有办法使得对方进入一个n=m的局面,此时我们就是必胜的。

所以我们的博弈状态为:

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

其他情况,此时我肯定不能把小的再切小,因为每次切割必然使得nm比原来的一半还小,就会使得对手进入W的必胜态。所以我一定是切割n, m中较大的那个,并且要尽可能大的切割。

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,背包,图论

我们将需要送外卖的点标记为need

定义dp状态:

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

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

考虑一下转移方程。

在转移刚开始的时候,dp[x]是不完整的,它仅包含x这一个点的信息,设x的儿子分别为y1,y2,y3,在将y1转移给x之后,dp[x]表示的范围就是x点y1子树,以此类推,将y2, y3一个个合并,最后dp[x]表示的信息就是以x为根的子树的信息。

思考一下如何更新dp[x][k],我们可以将k分解成i + (k - i),然后有dp[x][k] = max(dp[x][i], dp[y][k - i])

我们更新dp[x]需要用到dp[x]本身的信息,所以我们需要开一个临时的数组f[]来表示dp[x]更新完再将f[]复制给dp[x]

首先,如果s[y] == 0,说明y子树对答案完全没有影响,可以直接跳过。

如果k - i == s[y],说明我们把y子树的所有需求点都删了,那么x -> y这条边可以删除,所以对答案贡献为2(表示最终路程可以减少2),其余情况贡献都为0。

更新完dp[x]后还要更新一下s[x],直接加上s[y]即可。

同时顺便计算一下不删除边的情况下的总路程tot,当s[y]不为0,就必须往下走了。

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原创,创作不易,如果对您有帮助,欢迎小伙伴们点赞👍、收藏⭐、留言💬

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,641评论 6 525
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,754评论 3 408
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 173,075评论 0 370
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,369评论 1 303
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,386评论 6 402
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,800评论 1 317
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,122评论 3 431
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 41,130评论 0 281
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,689评论 1 327
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,693评论 3 348
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,804评论 1 356
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,399评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,128评论 3 341
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,528评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,705评论 1 278
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,409评论 3 383
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,878评论 2 368

推荐阅读更多精彩内容

  • 目录 1 左神部分集锦 2 Leetcode前150题 3 牛客网剑指offer 4 JavaG 5 题目中的...
    小小千千阅读 1,019评论 0 0
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,763评论 2 59
  • 1. 二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,...
    deactivateuser阅读 1,652评论 0 3
  • 前言 2. 实现 Singleton 3. 数组中重复的数字 4. 二维数组中的查找 5. 替换空格 6. 从尾到...
    Observer_____阅读 2,942评论 0 1
  • 归去来兮。 1.1 说明 本篇为《挑战程序设计竞赛(第2版)》[http://www.ituring.com.cn...
    尤汐Yogy阅读 14,377评论 0 160