AtCoder Weekday Contest 0011 Beta题解(AWC 0011 Beta A-E)

A - A Walk Along the Cherry Blossom Trees

【题目来源】

AtCoder:A - A Walk Along the Cherry Blossom Trees

【题目描述】

Takahashi is taking a walk along a road with \(N\) points arranged in a straight line. The points are numbered \(1, 2, \ldots, N\) from left to right, and points whose numbers differ by \(1\) are adjacent to each other.
高桥正在沿着一条有 \(N\) 个点排成直线的道路散步。这些点从左到右编号为 \(1, 2, …, N\),且编号相差 \(1\) 的点彼此相邻。

Along this road, \(M\) cherry blossom trees are planted. The \(i\)-th cherry blossom tree is planted at point \(P_i\), and when Takahashi visits that point, \(V_i\) petals fall down, all of which Takahashi receives. At most one cherry blossom tree is planted at each point.
沿着这条道路,种植了 \(M\) 棵樱花树。第 \(i\) 棵樱花树种在点 \(P_i\) 处,当高桥访问该点时,会有 \(V_i\) 片花瓣飘落,所有这些花瓣都被高桥接收。每个点最多种植一棵樱花树。

Takahashi starts at point \(S\) and moves to point \(T\). He proceeds one adjacent point at a time from \(S\) toward \(T\), without ever turning back. Therefore, the points Takahashi visits, including the start and goal points, are as follows:
高桥从点 \(S\) 出发,移动到点 \(T\)。他每次从 \(S\)\(T\) 移动一个相邻点,且从不回头。因此,高桥访问的点(包括起点和目标点)如下:

  • When \(S \leq T\): \(S, S+1, \ldots, T\)
  • When \(S > T\): \(S, S-1, \ldots, T\)

If \(S = T\), Takahashi does not move and only visits point \(S\).
如果 \(S = T\),高桥不移动,只访问点 \(S\)

Since Takahashi moves in only one direction, he visits each point exactly once. Find the total number of petals Takahashi receives while moving from point \(S\) to point \(T\).
由于高桥只朝一个方向移动,他恰好访问每个点一次。求高桥从点 \(S\) 移动到点 \(T\) 过程中接收到的花瓣总数。

【输入】

\(N\) \(M\)
\(S\) \(T\)
\(P_1\) \(V_1\)
\(P_2\) \(V_2\)
\(\vdots\)
\(P_M\) \(V_M\)

  • The first line contains \(N\), the number of points, and \(M\), the number of cherry blossom trees, separated by a space.
  • The second line contains \(S\), the start point, and \(T\), the goal point, separated by a space.
  • From the 3rd line to the \((M + 2)\)-th line, information about each cherry blossom tree is given.
  • The \((2 + i)\)-th line contains \(P_i\), the point where the \(i\)-th cherry blossom tree is planted, and \(V_i\), the number of petals that fall from that tree, separated by a space.

【输出】

Print in one line the total number of petals Takahashi receives while moving from point \(S\) to point \(T\).

【输入样例】

10 5
3 8
1 10
3 5
5 7
8 2
10 100

【输出样例】

14

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, s, t, ans;  // n: 总数量,m: 事件数量,s和t: 区间端点,ans: 结果

signed main()
{
    cin >> n >> m >> s >> t;  // 读入总数n、事件数m、区间端点s和t
    
    if (s > t)  // 确保s <= t
    {
        swap(s, t);
    }
    
    for (int i = 1; i <= m; i++)  // 处理每个事件
    {
        int p, v;  // p: 位置,v: 值
        cin >> p >> v;  // 读入位置和值
        
        if (p >= s && p <= t)  // 如果位置在区间[s, t]内
        {
            ans += v;  // 累加值
        }
    }
    
    cout << ans << endl;  // 输出结果
    return 0;
}

【运行结果】

10 5
3 8
1 10
3 5
5 7
8 2
10 100
14

B - Creating Mosaic Art

【题目来源】

AtCoder:B - Creating Mosaic Art

【题目描述】

Takahashi is going to create mosaic art for the school festival.
高桥要为学校文化节创作马赛克艺术。

First, Takahashi prepared a design draft in the form of a grid with \(H\) rows and \(W\) columns. Each cell of the grid is either # (filled) or . (blank).
首先,高桥准备了一份 \(H\)\(W\) 列的网格形式的设计草稿。网格的每个单元格要么是 #(填充),要么是 .(空白)。

Based on this design draft, Takahashi creates the mosaic art using the following procedure.
基于这份设计草稿,高桥按照以下步骤制作马赛克艺术。

Step 1: Enlargement
步骤 1:放大

Enlarge the design draft by a factor of \(K\) both vertically and horizontally. Specifically, replace each cell of the draft with a block of \(K\) rows and \(K\) columns filled with the same character, obtaining a grid of \((H \times K)\) rows and \((W \times K)\) columns consisting of # and ..
将设计草稿在垂直和水平方向上均放大 \(K\) 倍。具体而言,将草稿的每个单元格替换为一个 \(K\)\(K\) 列、填充相同字符的块,从而得到一个由 #. 组成的 \((H × K)\)\((W × K)\) 列的网格。

Step 2: Character Assignment
步骤 2:字符分配

In the \((H \times K)\) by \((W \times K)\) grid obtained in Step 1, replace all # with character \(c_1\) and all . with character \(c_2\). Here, \(c_1\) and \(c_2\) are each a single character that is either a lowercase English letter (az) or an uppercase English letter (AZ). It is possible that \(c_1\) and \(c_2\) are the same character.
在步骤 \(1\) 得到的 \((H × K)\)\((W × K)\) 列网格中,将所有 # 替换为字符 c_1,所有 . 替换为字符 c_2。此处,c_1c_2 各自是一个单独的字符,可以是小写英文字母(az)或大写英文字母(AZ)。\(c_1\)\(c_2\) 可能是相同的字符。

Output the resulting mosaic art of \((H \times K)\) rows and \((W \times K)\) columns.
输出得到的 \((H × K)\)\((W × K)\) 列的马赛克艺术。

【输入】

\(H\) \(W\) \(K\)
\(c_1\) \(c_2\)
\(S_1\)
\(S_2\)
\(\vdots\)
\(S_H\)

  • The first line contains the number of rows \(H\), the number of columns \(W\), and the enlargement factor \(K\) of the design draft, separated by spaces.
  • The second line contains the character \(c_1\) to replace # and the character \(c_2\) to replace ., separated by a space.
  • Over the following \(H\) lines, the design draft is given. The \(i\)-th \((1 \leq i \leq H)\) of these lines contains the string \(S_i\) corresponding to the \(i\)-th row from the top of the design draft. \(S_i\) is a string of length \(W\) consisting of # and ..

【输出】

Output the resulting mosaic art over \((H \times K)\) lines. Each line is a string of length \((W \times K)\).

【输入样例】

3 3 2
X o
#.#
.#.
#.#

【输出样例】

XXooXX
XXooXX
ooXXoo
ooXXoo
XXooXX
XXooXX

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 105 * 50;
char a[N][N], b[N][N], c1, c2;  // a: 原图案,b: 放大后的图案,c1/c2: 颜色字符
int n, m, k;  // n,m: 原图案行列数,k: 放大倍数

int main()
{
    cin >> n >> m >> k;  // 读入原图案的行列数和放大倍数
    cin >> c1 >> c2;  // 读入两种颜色字符
    
    // 读入原图案
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
        }
    }
    
    // 将原图案放大k倍
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            char c = a[i][j];  // 获取原图案中的字符
            int row = (i - 1) * k + 1, col = (j - 1) * k + 1;  // 计算在放大图案中的起始位置
            
            // 将原图案的一个点扩展为k*k的方块
            for (int x = 1; x <= k; x++)
            {
                for (int y = 1; y <= k; y++)
                {
                    b[row + x - 1][col + y - 1] = c;
                }
                // cout << endl;  // 注释掉的调试输出
            }
        }
    }
    
    // 替换颜色字符
    for (int i = 1; i <= n * k; i++)
    {
        for (int j = 1; j <= m * k; j++)
        {
            if (b[i][j] == '#')
            {
                b[i][j] = c1;  // 将#替换为c1
            }
            else
            {
                b[i][j] = c2;  // 将其他字符替换为c2
            }
        }
    }
    
    // 输出最终图案
    for (int i = 1; i <= n * k; i++)
    {
        for (int j = 1; j <= m * k; j++)
        {
            cout << b[i][j];
        }
        cout << endl;
    }
    return 0;
}

【运行结果】

3 3 2
X o
#.#
.#.
#.#
XXooXX
XXooXX
ooXXoo
ooXXoo
XXooXX
XXooXX

C - Maximum Number of Team Members

【题目来源】

AtCoder:C - Maximum Number of Team Members

【题目描述】

Takahashi is in charge of forming teams for a programming contest. There are \(N\) candidates, numbered from \(1\) to \(N\).
高桥负责为一个编程比赛组建队伍。有 \(N\) 名候选人,编号从 \(1\)\(N\)

Each candidate \(i\) represents the set of skills they are proficient in as a bit representation of a non-negative integer \(A_i\). Takahashi wants to select team members from these \(N\) people such that when the skills of all selected members are combined using bitwise OR, the team's overall skill set exactly matches the target value \(K\).
每位候选人 \(i\) 用非负整数 \(A_i\) 的二进制位表示来代表他们所精通的技能集合。高桥想从这 \(N\) 个人中选出团队成员,使得当选出所有成员时,用位或(OR)操作合并他们的技能后,团队的整体技能集恰好与目标值 \(K\) 匹配。

Takahashi wants to include as many people as possible in the team.
高桥希望让尽可能多的人加入团队。

Find the maximum number of candidates that can be selected from a non-empty subset of candidates such that the bitwise OR of all their skill values equals exactly \(K\). If no such subset exists, output \(-1\).
求可以从候选人的非空子集中选出的最大候选人数量,使得他们所有技能值的位或运算结果恰好等于 \(K\)。如果不存在这样的子集,则输出 \(-1\)

【输入】

\(N\) \(K\)
\(A_1\) \(A_2\) \(\ldots\) \(A_N\)

  • The first line contains \(N\), the number of candidates, and \(K\), the target OR value, separated by a space.
  • The second line contains the skill values \(A_1, A_2, \ldots, A_N\) of each candidate, separated by spaces.

【输出】

Output in one line the maximum number of elements in a non-empty subset of candidates whose bitwise OR of skill values equals exactly \(K\). If no such subset exists, output \(-1\).

【输入样例】

5 7
3 5 6 1 9

【输出样例】

4

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, k, ans, cnt;  // n: 数字个数,k: 目标值,ans: 按位或结果,cnt: 满足条件的数字个数

signed main()
{
    cin >> n >> k;  // 读入数字个数和目标值
    
    for (int i = 1; i <= n; i++)  // 遍历所有数字
    {
        int x; 
        cin >> x;  // 读入当前数字
        
        // 检查当前数字是否不会引入k中不存在的1
        if ((x | k) == k)  // 即检查x的所有1位在k中也是1
        {
            ans |= x;  // 将x的1位加入ans
            cnt++;  // 计数器加1
        }
    }
    
    // 如果按位或结果等于k,且至少有一个数字满足条件
    if (ans == k && cnt > 0)
    {
        cout << cnt << endl;  // 输出满足条件的数字个数
    }
    else
    {
        cout << -1 << endl;  // 否则输出-1
    }
    
    return 0;
}

【运行结果】

5 7
3 5 6 1 9
4

D - Family Tree and Inheritance

【题目来源】

AtCoder:D - Family Tree and Inheritance

【题目描述】

Takahashi is investigating his family's genealogy. The family consists of \(N\) people, each numbered from \(1\) to \(N\).
高桥正在调查他家的族谱。这个家族由 \(N\) 人组成,每个人编号从 \(1\)\(N\)

In this family tree, every person except person \(1\), who is the founding ancestor, has exactly one "parent." The parent of person \(i\) (\(2 \leq i \leq N\)) is person \(P_i\). Through these parent-child relationships, all people form a rooted tree with person \(1\) as the root.
在这棵家族树中,除了作为始祖的人 \(1\) 之外,每个人恰好有一个"父节点"。人 \(i\)\(2 ≤ i ≤ N\))的父节点是人 \(P_i\)。通过这些父子关系,所有人形成一棵以人 \(1\) 为根的有根树。

For each person \(i\), the value \(V_i\) of the inheritance left by that person is recorded.
对于每个人 \(i\),记录有该人留下的遗产价值 \(V_i\)

Takahashi defines the "cumulative inheritance" of a person \(X\) as the sum of the inheritance values of all people on the path from person \(X\) to the founding ancestor (person \(1\)), obtained by repeatedly following the parent, including both person \(X\) themselves and person \(1\).
高桥将一个人 \(X\) 的"累计遗产"定义为从人 \(X\) 到始祖(人 \(1\))的路径上所有人的遗产价值之和,这条路径通过不断跟随父节点获得,包括人 \(X\) 自身和人 \(1\)

You are given \(Q\) queries. For each query, a person number \(X_j\) is specified. Find the cumulative inheritance of that person.
你被给予了 \(Q\) 条查询。对于每条查询,会指定一个人编号 \(X_j\)。求该人的累计遗产。

【输入】

The input is given from standard input in the following format.

\(N\) \(Q\)
\(V_1\) \(V_2\) \(\ldots\) \(V_N\)
\(P_2\) \(P_3\) \(\ldots\) \(P_N\)
\(X_1\)
\(X_2\)
\(\vdots\)
\(X_Q\)

  • The first line contains the number of people \(N\) and the number of queries \(Q\), separated by a space.
  • The second line contains the inheritance values \(V_1, V_2, \ldots, V_N\) of each person, separated by spaces.
  • The third line contains the parent numbers \(P_2, P_3, \ldots, P_N\) for persons \(2\) through \(N\), separated by spaces. When \(N = 1\), this line is empty.
  • Each of the following \(Q\) lines contains a single person number specified for each query. Specifically, the \(j\)-th of these lines (\(1 \leq j \leq Q\)) contains \(X_j\).

【输出】

Output \(Q\) lines. On the \(j\)-th line (\(1 \leq j \leq Q\)), output the cumulative inheritance of person \(X_j\) specified in the \(j\)-th query as an integer.

\(ans_1\)
\(ans_2\)
\(\vdots\)
\(ans_Q\)

【输入样例】

5 3
10 20 30 40 50
1 1 2 2
1
4
5

【输出样例】

10
70
80

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005, M = N * 2;
int n, q;  // n: 节点数,q: 查询次数
int h[N], e[M], ne[M], w[M], idx;  // 邻接表存储树
int v[N], d[N];  // v: 节点值,d: 从根到当前节点的前缀和

// 添加无向边
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

// DFS遍历树,计算前缀和
void dfs(int u, int fa)
{
    d[u] = v[u] + d[fa];  // 当前节点的前缀和 = 节点值 + 父节点的前缀和
    for (int i = h[u]; i != -1; i = ne[i])  // 遍历邻接点
    {
        int j = e[i];
        if (j == fa)  // 避免回到父节点
        {
            continue;
        }
        if (j)  // 如果邻接点存在
        {
            dfs(j, u);
        }
    }
}

signed main()
{
    memset(h, -1, sizeof(h));  // 初始化邻接表
    cin >> n >> q;  // 读入节点数和查询次数
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i];  // 读入每个节点的值
    }
    for (int i = 2; i <= n; i++)  // 建树
    {
        int p; 
        cin >> p;  // 读入父节点
        add(p, i);  // 添加从父节点到子节点的边
        add(i, p);  // 添加从子节点到父节点的边
    }
    dfs(1, 0);  // 从根节点1开始DFS,父节点为0
    
    while (q--)  // 处理查询
    {
        int x; 
        cin >> x;  // 读入查询的节点
        cout << d[x] << endl;  // 输出从根到节点x的前缀和
    }
    return 0;
}

【运行结果】

5 3
10 20 30 40 50
1 1 2 2
1
10
4
70
5
80
posted @ 2026-03-05 11:30  团爸讲算法  阅读(0)  评论(0)    收藏  举报