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

A - Announcement of Winning Numbers

【题目来源】

AtCoder:A - Announcement of Winning Numbers

【题目描述】

Takahashi is a staff member at a shopping district's lottery event. In this event, \(N\) visitors draw the lottery one by one in order.
高桥是商业街抽奖活动的工作人员。在这次活动中,\(N\) 名参观者按顺序逐一抽奖。

Each visitor has two types of numbers. The \(i\)-th \((1 \leq i \leq N)\) visitor to draw the lottery is assigned a sequence number \(i\) in the order they drew. Additionally, each visitor received a participation ticket at registration, and the participation ticket number of the \(i\)-th visitor to draw the lottery is \(A_i\). Note that different visitors may have the same participation ticket number.
每位参观者有两种编号。第 \(i\) 个(\(1 \leq i \leq N\))抽奖的参观者按其抽奖顺序被分配了一个顺序号 \(i\)。此外,每位参观者在登记时收到了一张参与券,第 \(i\) 个抽奖参观者的参与券编号\(A_i\)。注意,不同的参观者可能有相同的参与券编号。

Takahashi's task is to give a prize to every visitor whose sequence number is a multiple of \(K\) (i.e., \(K, 2K, 3K, \ldots\)). Since \(K \leq N\), there is at least one visitor who receives a prize.
高桥的任务是向每位顺序号是 \(K\) 的倍数的参观者发放奖品(即 \(K, 2K, 3K, \ldots\))。由于 \(K \leq N\),至少有一位参观者会获得奖品。

Output all participation ticket numbers of the visitors who receive prizes, in ascending order of their sequence numbers. If multiple visitors have the same participation ticket number, output that number as-is without removing duplicates.
按顺序号升序输出所有获得奖品的参观者的参与券编号。如果多名参观者有相同的参与券编号,则按原样输出该编号,不去重。

【输入】

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

  • The first line contains an integer \(N\) representing the number of visitors and an integer \(K\) representing the criterion for giving prizes, separated by a space. Prizes are given to visitors whose sequence numbers are multiples of \(K\).
  • The second line contains \(N\) integers \(A_i\), each representing the participation ticket number of the \(i\)-th visitor to draw the lottery, separated by spaces.

【输出】

Output the participation ticket numbers of the visitors who receive prizes in ascending order of their sequence numbers, separated by spaces on a single line, followed by a newline.

【输入样例】

6 2
10 20 30 40 50 60

【输出样例】

20 40 60

【代码详解】

#include <bits/stdc++.h>  // 包含所有标准库头文件
using namespace std;       // 使用标准命名空间

// #define int long long  // 注释掉了,如果需要大整数可以取消注释
const int N = 200005;  // 定义常量N,表示数组最大容量

int n, k, cur;  // n: 输入数字总数, k: 间隔, cur: 结果数组的当前索引
int a[N];       // 结果数组,存储筛选后的数字

int main()  // 主函数入口
{
    cin >> n >> k;  // 输入数字总数n和间隔k
    
    // 遍历输入的n个数字
    for (int i = 1; i <= n; i++)
    {
        int x;  // 临时变量,存储当前输入的数字
        cin >> x;  // 读取第i个数字
        
        // 如果当前索引i能被k整除(即i是k的倍数)
        if (i % k == 0)
        {
            a[++cur] = x;  // 将数字x存入结果数组a,cur先自增再使用
        }
    }
    
    // 输出筛选后的数字
    for (int i = 1; i <= cur; i++)
    {
        cout << a[i] << " ";  // 输出结果数组中的第i个元素,后跟空格
    }
    cout << endl;  // 输出换行符,结束输出
    
    return 0;  // 程序正常结束
}

【运行结果】

6 2
10 20 30 40 50 60
20 40 60

B - Distribution of Jewels

【题目来源】

AtCoder:B - Distribution of Jewels

【题目描述】

Takahashi and Aoki are playing a game where they distribute gems flowing on a conveyor belt.
高桥和青木正在玩一个分配传送带上宝石的游戏。

At the beginning of the game, a positive integer \(K\) is determined. This is the upper limit on the total value of gems that Takahashi can take.
游戏开始时,确定一个正整数 \(K\)。这是高桥可以拿取的宝石总价值的上限。

\(N\) gems flow on the conveyor belt in order, from the \(1\)-st to the \(N\)-th. The value of the \(i\)-th gem is \(A_i\) (a positive integer).
\(N\) 颗宝石按顺序从第 \(1\) 颗到第 \(N\) 颗在传送带上流动。第 \(i\) 颗宝石的价值为 \(A_i\)(一个正整数)。

Each time a gem flows by, whether Takahashi takes it is determined according to the following rules:
每当一颗宝石流过时,高桥是否拿取它由以下规则决定:

  • If taking the gem would keep the total value of gems he has taken so far (including this gem) at most \(K\), he takes the gem.
    如果拿取这颗宝石能使他至今拿取的宝石总价值(包括这颗宝石)不超过 \(K\),则他拿取这颗宝石。
  • Otherwise (if taking the gem would cause the total to exceed \(K\)), he does not take the gem.
    否则(如果拿取这颗宝石会使总价值超过 \(K\)),他不拿取这颗宝石。

In other words, Takahashi greedily takes gems in order from the first, as long as the total does not exceed \(K\).
换句话说,高桥从第一颗开始贪心地按顺序拿取宝石,只要总价值不超过 \(K\)

Aoki receives all the gems that Takahashi did not take. Aoki has no choice in the matter.
青木收到所有高桥没有拿取的宝石。青木对此没有选择权。

After all \(N\) gems have flowed by, the total value of gems Takahashi took and the total value of gems Aoki received are compared. The one with the greater total wins, and if the totals are equal, it is a draw.
\(N\) 颗宝石全部流过之后,比较高桥拿取的宝石总价值和青木收到的宝石总价值。总价值更高的一方获胜,如果总价值相等,则为平局。

Given the number of gems \(N\), the upper limit \(K\), and the sequence of values of the \(N\) gems \(A_1, A_2, \ldots, A_N\), determine the result of the game.
给定宝石数量 \(N\)、上限 \(K\) 以及 \(N\) 颗宝石的价值序列 \(A_1, A_2, \ldots, A_N\),确定游戏的结果。

【输入】

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

  • The first line contains the integer \(N\) representing the number of gems and the integer \(K\) representing the upper limit on the total value of gems Takahashi can take, separated by a space.
  • The second line contains the values of the \(N\) gems \(A_1, A_2, \ldots, A_N\) in the order they flow by, separated by spaces.

【输出】

If Takahashi wins, print Takahashi; if Aoki wins, print Aoki; if it is a draw, print Draw, on a single line.

【输入样例】

5 10
3 4 2 8 1

【输出样例】

Takahashi

【代码详解】

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

int n, k, sum;
int a[N];

signed main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        sum += a[i];  // 计算总和
    }
    int res = 0;
    // 从前往后取,直到不能取为止
    for (int i = 1; i <= n; i++)
    {
        if (res + a[i] <= k)
        {
            res += a[i];
        }
    }
    // 比较两人获得的糖果数量
    if (res < (sum - res))
    {
        cout << "Aoki" << endl;  // 后手Aoki赢
    }
    else if (res > (sum - res))
    {
        cout << "Takahashi" << endl;  // 先手Takahashi赢
    }
    else
    {
        cout << "Draw" << endl;  // 平局
    }
    return 0;
}

【运行结果】

5 10
3 4 2 8 1
Takahashi

C - Field Trip Snacks

【题目来源】

AtCoder:C - Field Trip Snacks

【题目描述】

Takahashi is choosing snacks to bring on a field trip. The store has \(N\) types of snacks, and snack \(i\) (\(1 \le i \le N\)) costs \(P_i\) yen per piece. Each type of snack is available in sufficient quantity.
高桥正在选择要带去郊游的零食。商店有 \(N\) 种零食,零食 \(i\)\(1 \le i \le N\))每件售价 \(P_i\) 日元。每种零食都有充足的供应。

Takahashi selects some types from the \(N\) types of snacks, and buys exactly \(T\) pieces of each selected type. He does not buy any pieces of the types he did not select.
高桥从这 \(N\) 种零食中选择一些种类,并为每种选中的零食恰好购买 \(T\) 件。对于未选中的种类,他不购买任何件。

The total amount spent on snacks must be at most \(E\) yen. Within this budget, what is the maximum number of types of snacks he can buy?
购买零食的总金额必须不超过 \(E\) 日元。在此预算内,他最多能购买多少种不同的零食?

In other words, find the maximum value of \(|S|\) when choosing a set \(S \subseteq \{1, 2, \ldots, N\}\) of types to buy such that \(\displaystyle \sum_{i \in S} P_i \times T \le E\).
换句话说,当选择一个要购买的零食种类集合 \(S \subseteq \{1, 2, \ldots, N\}\) 使得 \(\displaystyle \sum_{i \in S} P_i \times T \le E\) 时,求 \(|S|\) 的最大值。

【输入】

\(N\) \(T\) \(E\)
\(P_1\) \(P_2\) \(\ldots\) \(P_N\)

  • The first line contains an integer \(N\) representing the number of types of snacks, an integer \(T\) (pieces) representing the number of pieces to buy of each selected type, and an integer \(E\) (yen) representing the budget, separated by spaces.
  • The second line contains integers \(P_1, P_2, \ldots, P_N\) (yen) representing the price per piece of each snack, separated by spaces.

【输出】

Print the maximum number of types of snacks that can be bought, in a single line.

【输入样例】

5 2 20
3 5 1 4 7

【输出样例】

3

【代码详解】

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

int n, t, e;
int p[N];

signed main()
{
    cin >> n >> t >> e;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        x *= t;  // 计算每个项目需要的能量
        p[i] = x;
    }
    // 按能量需求从小到大排序
    sort(p + 1, p + n + 1);
    int cnt = 0, sum = 0;
    // 贪心选择:从能量需求小的开始选择
    for (int i = 1; i <= n; i++)
    {
        if (sum + p[i] <= e)  // 如果当前总能量不超过限制
        {
            sum += p[i];
            cnt++;
        }
        else
        {
            break;
        }
    }
    cout << cnt << endl;
    return 0;
}

【运行结果】

5 2 20
3 5 1 4 7
3

D - Repainted Wall

【题目来源】

AtCoder:D - Repainted Wall

【题目描述】

Takahashi is painting a long horizontal wall with paint.
高桥正在用油漆粉刷一堵长长的水平墙壁。

The wall extends across the entire number line, and initially, every point on the number line has been painted \(0\) times. Takahashi performed \(N\) painting operations. In the \(i\)-th operation \((1 \leq i \leq N)\), he painted the interval \([L_i, R_i]\) (where \(L_i < R_i\)) once. That is, for every point corresponding to a real number \(x\) satisfying \(L_i \leq x \leq R_i\), the number of times it has been painted increased by \(1\).
这面墙覆盖了整个数轴,初始时,数轴上的每个点都被粉刷了 \(0\) 次。高桥进行了 \(N\) 次粉刷操作。在第 \(i\) 次操作(\(1 \leq i \leq N\))中,他粉刷了区间 \([L_i, R_i]\)(其中 \(L_i < R_i\))一次。也就是说,对于每个满足 \(L_i \leq x \leq R_i\) 的实数 \(x\) 对应的点,其被粉刷的次数增加了 \(1\)

Parts that have been painted \(K\) or more times are considered sufficiently thick and pass inspection, while parts painted fewer than \(K\) times are too thin and fail.
被粉刷 \(K\) 次或更多次的区域被认为是足够厚的并通过检查,而被粉刷少于 \(K\) 次的区域则太薄而未通过。

After all operations are completed, find the total length of the set of all points that have been painted \(K\) or more times (that is, the sum of the lengths of each interval that constitutes this set).
在所有操作完成后,求被粉刷 \(K\) 次或更多次的所有点组成的集合的总长度(即构成该集合的每个区间长度之和)。

For example, if the set of all points painted \(K\) or more times is the union of intervals \([1, 5]\) and \([7, 9]\), the answer is \((5 - 1) + (9 - 7) = 6\).
例如,如果被粉刷 \(K\) 次或更多次的所有点组成的集合是区间 \([1, 5]\)\([7, 9]\) 的并集,则答案为 \((5 - 1) + (9 - 7) = 6\)

Note that since all \(L_i\) and \(R_i\) are integers, the boundaries where the paint count changes occur only at integer coordinates. Therefore, the answer is always an integer.
注意,由于所有 \(L_i\)\(R_i\) 都是整数,油漆次数变化的边界仅出现在整数坐标处。因此,答案总是一个整数。

【输入】

\(N\) \(K\)
\(L_1\) \(R_1\)
\(L_2\) \(R_2\)
\(\vdots\)
\(L_N\) \(R_N\)

  • The first line contains an integer \(N\) representing the number of painting operations and an integer \(K\) representing the threshold number of coats required to pass inspection, separated by a space.
  • The \(i\)-th of the following \(N\) lines \((1 \leq i \leq N)\) contains the left endpoint \(L_i\) and right endpoint \(R_i\) of the interval painted in the \(i\)-th operation, separated by a space.

【输出】

Output the total length of the set of all points painted \(K\) or more times, as an integer on a single line.

【输入样例】

3 2
1 5
3 7
6 9

【输出样例】

3

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, k, ans, cnt;  // n: 区间数量,k: 阈值,ans: 总长度,cnt: 当前覆盖次数
map<int, int> mp;  // 差分映射:key为坐标,value为变化量

int main()
{
    cin >> n >> k;  // 读入区间数量和阈值
    
    for (int i = 1; i <= n; i++)  // 处理每个区间
    {
        int l, r; 
        cin >> l >> r;  // 读入区间左端点和右端点
        mp[l]++;  // 在l处进入区间,覆盖次数+1
        mp[r]--;  // 在r处离开区间,覆盖次数-1
    }
    
    int last = 0, cnt = 0;  // last: 上一个坐标点,cnt: 当前覆盖次数
    
    // 扫描线遍历所有关键点
    for (auto x : mp)  // 按坐标从小到大遍历
    {
        int pos = x.first;  // 当前坐标
        int delta = x.second;  // 覆盖次数的变化量
        
        if (cnt >= k)  // 如果上一个区间的覆盖次数≥k
        {
            // 累加上一个区间[last, pos)的长度
            ans += pos - last;
        }
        
        last = pos;  // 更新上一个坐标
        cnt += delta;  // 更新当前覆盖次数
    }
    
    cout << ans << endl;  // 输出总长度
    return 0;
}

【运行结果】

3 2
1 5
3 7
6 9
3

E - Just the Right Temperature Difference

【题目来源】

AtCoder:E - Just the Right Temperature Difference

【题目描述】

Takahashi works at a weather observatory and is recording the daily maximum temperatures over \(N\) days for a certain region. The maximum temperature on day \(i\) (\(1 \leq i \leq N\)) is \(A_i\) ℃.
高桥在气象观测站工作,正在记录某个地区连续 \(N\) 天的日最高气温。第 \(i\) 天(\(1 \leq i \leq N\))的最高气温为 \(A_i\) ℃。

Takahashi wants to select a contiguous interval of days and examine the temperature fluctuation range. For an interval from day \(l\) to day \(r\) (\(1 \leq l \leq r \leq N\)), the "fluctuation range" of that interval is defined as:
高桥想选择一个连续的天数区间,并检查其温度波动范围。对于从第 \(l\) 天到第 \(r\) 天(\(1 \leq l \leq r \leq N\))的区间,该区间的"波动范围"定义为:

\(\max(A_l, A_{l+1}, \dots, A_r) - \min(A_l, A_{l+1}, \dots, A_r)\)

In particular, when \(l = r\) (an interval consisting of only one day), the fluctuation range is \(0\).
特别地,当 \(l = r\)(只包含一天的区间)时,波动范围为 \(0\)

Given a positive integer \(N\), a non-negative integer \(K\), and a sequence of maximum temperatures over \(N\) days \(A_1, A_2, \dots, A_N\), find the number of intervals whose fluctuation range is exactly \(K\). That is, find the number of integer pairs \((l, r)\) (\(1 \leq l \leq r \leq N\)) satisfying:
给定一个正整数 \(N\)、一个非负整数 \(K\),以及 \(N\) 天的最高气温序列 \(A_1, A_2, \dots, A_N\),求波动范围恰好为 \(K\) 的区间数量。也就是说,求满足以下条件的整数对 \((l, r)\)\(1 \leq l \leq r \leq N\))的数量:

\(\max(A_l, A_{l+1}, \dots, A_r) - \min(A_l, A_{l+1}, \dots, A_r) = K\)

【输入】

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

The first line contains a positive integer \(N\) representing the number of days and a non-negative integer \(K\) representing the specified fluctuation range, separated by a space. The second line contains integers \(A_1, A_2, \dots, A_N\) representing the maximum temperature on each day, separated by spaces.

【输出】

Output the number of pairs \((l, r)\) whose fluctuation range is exactly \(K\), on a single line.

【输入样例】

5 3
1 4 2 5 3

【输出样例】

6

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int n, k;
int a[N], ans;
struct Node
{
    int v, idx;  // v: 数组值, idx: 在数组中的下标
};


// 计算最大值与最小值之差不超过k的区间数量
int calc(int k)
{
    int res = 0;           // 结果计数器
    int l = 1, r = 1;      // 双指针,表示当前区间[l, r]
    deque<Node> dqmin, dqmax;  // 单调队列,分别维护最小值和最大值
    
    while (l <= n && r <= n)  // 双指针遍历数组
    {
        // 将a[r]加入最小值队列(维护单调递增)
        while (!dqmin.empty() && dqmin.back().v >= a[r])
        {
            dqmin.pop_back();  // 移除队尾比a[r]大的元素
        }
        dqmin.push_back({a[r], r});  // 将a[r]加入队列

        // 将a[r]加入最大值队列(维护单调递减)
        while (!dqmax.empty() && dqmax.back().v <= a[r])
        {
            dqmax.pop_back();  // 移除队尾比a[r]小的元素
        }
        dqmax.push_back({a[r], r});  // 将a[r]加入队列

        // 调整左指针l,使当前区间[l, r]的最大值-最小值<=k
        while (!dqmin.empty() && !dqmax.empty() && dqmax.front().v - dqmin.front().v > k)
        {
            // 如果队首元素是左指针l指向的元素,则从队列中移除
            if (dqmax.front().idx == l)
            {
                dqmax.pop_front();  // 从最大值队列中移除过期的元素
            }
            if (dqmin.front().idx == l)
            {
                dqmin.pop_front();  // 从最小值队列中移除过期的元素
            }
            l++;  // 左指针右移,缩小区间
        }
        r++;  // 右指针右移,扩展区间
        
        // 统计以r-1为右端点的满足条件的区间数量
        // 区间[l, r-1]满足条件,所以有(r-1)-l+1 = r-l+1个区间
        res += r - l + 1;
    }
    return res;  // 返回差值不超过k的区间总数
}

signed main()
{
    cin >> n >> k;  // 读入数组长度n和差值限制k
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];  // 读入数组元素
    }

    // 差值恰好等于k的区间数 = 差值不超过k的区间数 - 差值不超过k-1的区间数
    cout << calc(k) - calc(k - 1) << endl;
    return 0;
}

【运行结果】

5 3
1 4 2 5 3
6
posted @ 2026-03-17 14:50  团爸讲算法  阅读(3)  评论(0)    收藏  举报