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

A - Loading Cargo

【题目来源】

AtCoder:A - Loading Cargo

【题目描述】

Takahashi works at a shipping company. Today, he is in charge of loading cargo onto \(N\) trucks.
高桥在一家运输公司工作。今天,他负责将货物装载到 \(N\) 辆卡车上。

The items to be loaded onto truck \(i\) \((1 \leq i \leq N)\) all have the same weight of \(P_i\) kilograms each. Takahashi loads these items one by one.
要装载到卡车 \(i\)\(1 ≤ i ≤ N\))上的物品每件重量相同,均为 \(P_i\) 公斤。高桥将这些物品一件一件地装载。

Every truck has a common weight capacity of \(T\) kilograms. When loading \(k\) items onto truck \(i\), the total weight of the items must not exceed \(T\) kilograms. That is, \(P_i \times k \leq T\) must hold.
每辆卡车都有一个共同的载重量限制 \(T\) 公斤。当将 \(k\) 件物品装载到卡车 \(i\) 上时,物品的总重量不得超过 \(T\) 公斤。也就是说,必须满足 \(P_i × k ≤ T\)

Furthermore, there is a common upper limit of \(R\) items on the number of items that can be loaded onto each truck. Even if the weight capacity has not been reached, loading for that truck ends once \(R\) items have been loaded.
此外,每辆卡车可装载的物品数量有一个共同的上限 \(R\) 件。即使尚未达到重量限制,一旦装载了 \(R\) 件物品,对该辆卡车的装载就会结束。

For each truck \(i\), determine the maximum number of items \(r_i\) that can be loaded while satisfying both the weight capacity and the item count limit.
对于每辆卡车 \(i\),确定在满足重量限制和物品数量限制的前提下,可装载的最大物品数量 \(r_i\)

【输入】

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

  • The first line contains an integer \(N\) representing the number of trucks, an integer \(R\) representing the upper limit on the number of items that can be loaded onto each truck, and an integer \(T\) representing the weight capacity, separated by spaces.
  • The second line contains integers \(P_1, P_2, \ldots, P_N\) representing the weight of one item to be loaded onto each truck, separated by spaces.

【输出】

Output \(N\) integers \(r_1, r_2, \ldots, r_N\) separated by spaces on a single line, where \(r_i\) is the maximum number of items that can be loaded onto truck \(i\).

【输入样例】

3 5 20
3 5 7

【输出样例】

5 4 2

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int n, r, t;  // n: 数组长度,r: 上限值,t: 总资源
int p[N];  // 数组p

signed main()
{
    cin >> n >> r >> t;  // 读入数组长度、上限值和总资源
    for (int i = 1; i <= n; i++)
    {
        cin >> p[i];  // 读入每个p[i]
    }
    
    for (int i = 1; i <= n; i++)
    {
        // 输出结果:取上限值r和(t/p[i])的较小值
        // 由于t/p[i]可能是小数,这里会截断为整数
        // 加上(long long)确保类型转换
        cout << min(r, (long long)t / p[i]) << " ";
    }
    
    return 0;
}

【运行结果】

3 5 20
3 5 7
5 4 2 

B - Marathon

【题目来源】

AtCoder:B - Marathon

【题目描述】

Takahashi and Aoki are participating in a marathon race. The marathon course has \(N\) checkpoints, and runners pass through them in order from the \(1\)-st to the \(N\)-th.
高桥和青木正在参加一场马拉松比赛。马拉松赛道有 \(N\) 个检查点,跑者按顺序从第 \(1\) 个到第 \(N\) 个通过它们。

The distance from the \(i\)-th checkpoint to the \((i + 1)\)-th checkpoint is \(D_i\) meters (\(1 \leq i \leq N-1\)).
从第 \(i\) 个检查点到第 \((i+1)\) 个检查点的距离是 \(D_i\) 米(\(1 ≤ i ≤ N-1\))。

At the start of the race (time \(0\) seconds), both of them started simultaneously from the \(1\)-st checkpoint.
在比赛开始时(\(0\) 秒时),两人同时从第 \(1\) 个检查点出发。

Takahashi runs at a constant pace without taking any breaks, advancing at a speed of \(V\) meters per second. Therefore, the time at which Takahashi arrives at the \(i\)-th checkpoint (\(2 \leq i \leq N\)) is \(\displaystyle\frac{D_1 + D_2 + \cdots + D_{i-1}}{V}\) seconds. This value is not necessarily an integer.
高桥以恒定的速度跑步,没有任何休息,以每秒 \(V\) 米的速度前进。因此,高桥到达第 \(i\) 个检查点(\(2 ≤ i ≤ N\))的时间是 \(\displaystyle\frac{D_1 + D_2 + \cdots + D_{i-1}}{V}\) 秒。这个值不一定是整数。

On the other hand, Aoki runs at an uneven pace, and it is known that he arrives at the \(i\)-th checkpoint at exactly time \(T_i\) seconds. Here, \(T_1 = 0\). Aoki's arrival times satisfy \(T_1 < T_2 < T_3 < \cdots < T_N\).
另一方面,青木的跑步速度不均匀,已知他正好在 \(T_i\) 秒时到达第 \(i\) 个检查点。这里,\(T_1 = 0\)。青木的到达时间满足 \(T_1 < T_2 < T_3 < \cdots < T_N\)

For each checkpoint \(i\) from the \(2\)-nd onward (\(2 \leq i \leq N\)), if Takahashi's arrival time is strictly less than Aoki's arrival time \(T_i\), that is, if
对于从第 \(2\) 个开始的每个检查点 \(i\)\(2 ≤ i ≤ N\)),如果高桥的到达时间严格小于青木的到达时间 \(T_i\),也就是说,如果

\(D_1 + D_2 + \cdots + D_{i-1} < T_i \times V\)

holds, then Takahashi is said to have arrived first at checkpoint \(i\) ahead of Aoki. If they arrive at the same time, it does not count as arriving first.
成立,则称高桥在检查点 \(i\) 比青木先到。如果他们同时到达,则不计为先到。

Find all checkpoint numbers where Takahashi arrives first ahead of Aoki, and output them in ascending order. If there are no such checkpoints, output -1.
找出所有高桥比青木先到的检查点编号,并按升序输出。如果不存在这样的检查点,输出 -1

【输入】

\(N\) \(V\)
\(D_1\) \(D_2\) \(\cdots\) \(D_{N-1}\)
\(T_2\) \(T_3\) \(\cdots\) \(T_N\)

  • The first line contains the number of checkpoints \(N\) and Takahashi's speed \(V\) (meters per second), separated by a space.
  • The second line contains \(N - 1\) distances \(D_i\) (meters) from the \(i\)-th checkpoint to the \((i + 1)\)-th checkpoint (in order of \(i = 1, 2, \ldots, N-1\)), separated by spaces.
  • The third line contains \(N - 1\) arrival times \(T_i\) (seconds) at which Aoki arrives at the \(i\)-th checkpoint (in order of \(i = 2, 3, \ldots, N\)), separated by spaces. \(T_1 = 0\) is not included in the input.

【输出】

Output the checkpoint numbers where Takahashi arrives first ahead of Aoki, in ascending order, separated by spaces, on a single line. If there are no such checkpoints, output -1.

【输入样例】

5 10
30 50 40 60
4 10 15 20

【输出样例】

2 3 4 5

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int n, v, ans[N], cur;  // n: 车站数,v: 速度,ans: 结果数组,cur: 结果数量
int d[N], sd[N], t[N];  // d: 相邻站距离,sd: 距离前缀和,t: 时间限制

signed main()
{
    cin >> n >> v;  // 读入车站数和速度
    
    for (int i = 2; i <= n; i++)  // 从第2个车站开始
    {
        cin >> d[i];  // 读入相邻车站间的距离
        sd[i] = sd[i - 1] + d[i];  // 计算距离前缀和(从第1个车站到第i个车站的总距离)
    }
    
    for (int i = 2; i <= n; i++)
    {
        cin >> t[i];  // 读入从第1个车站到第i个车站的时间限制
    }
    
    for (int i = 2; i <= n; i++)  // 从第2个车站开始检查
    {
        // 如果实际需要的时间(sd[i]/v)小于时间限制t[i],说明可以在限制时间内到达
        if (sd[i] / v < t[i])
        {
            ans[++cur] = i;  // 记录车站编号
        }
    }
    
    if (cur == 0)  // 如果没有满足条件的车站
    {
        cout << -1;
    }
    else
    {
        for (int i = 1; i <= cur; i++)
        {
            cout << ans[i] << " ";  // 输出满足条件的车站编号
        }
        cout << endl;
    }
    return 0;
}

【运行结果】

5 10
30 50 40 60
4 10 15 20
2 3 4 5

C - Catch the Last Train!

【题目来源】

AtCoder:C - Catch the Last Train!

【题目描述】

Takahashi is heading to the station to catch the last train.
高桥正赶往车站去搭乘末班车。

Takahashi is at coordinate \(0\) on a number line, and the station is at coordinate \(G\) (\(G > 0\)). Meanwhile, the last train is currently at coordinate \(M\) and is heading toward Takahashi's direction, toward the station. After arriving at the station, the train will depart and leave.
高桥在数轴上坐标为 \(0\) 的位置,车站在坐标 \(G\) 处(\(G > 0\))。同时,末班车目前在坐标 \(M\) 处,正朝高桥的方向驶向车站。到达车站后,列车将出发并离开。

Normally, Takahashi can move at a speed of \(1\) per second, but by performing a "full sprint," his speed becomes \(D\) times faster for that second. However, due to stamina limitations, he can only sprint for a total of \(K\) seconds.
通常,高桥可以以每秒 \(1\) 的速度移动,但通过进行"全力冲刺",他在那一秒内的速度会变为 \(D\) 倍。然而,由于体力限制,他总共只能冲刺 \(K\) 秒。

The last train is moving toward the station at a speed of \(V\) per second. Since the stopping time between the train's arrival at the station and its departure is instantaneous, if the last train passes through the station before Takahashi arrives, he cannot board the train.
末班车正以每秒 \(V\) 的速度向车站移动。由于列车到达车站和出发之间的停靠时间可以忽略不计,如果末班车在高桥到达之前经过车站,他将无法上车。

Determine whether Takahashi can catch the last train if he uses his full sprints optimally.
判断如果高桥最优地使用他的全力冲刺,他能否赶上末班车。

Note that Takahashi and the last train start moving simultaneously. Takahashi can board the last train if the train has also arrived at the station by the moment Takahashi reaches the station (including the case where they arrive at the same time).
注意,高桥和末班车同时开始移动。如果高桥到达车站的时刻,列车也已到达车站(包括同时到达的情况),高桥就可以登上末班车。

【输入】

\(G\) \(M\) \(D\) \(K\) \(V\)

  • The first line contains the station's coordinate \(G\), the last train's initial coordinate \(M\), the speed multiplier during full sprint \(D\), the number of seconds full sprint can be used \(K\), and the last train's speed \(V\), separated by spaces.

【输出】

If Takahashi can catch the last train, print Yes; otherwise, print No.

【输入样例】

10 30 3 2 1

【输出样例】

Yes

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;

// 声明全局变量
// g: 高桥到车站的距离
// m: 列车初始位置坐标
// d: 冲刺时的速度倍率
// k: 可冲刺的总秒数
// v: 列车的移动速度
long double g, m, d, k, v;

signed main()
{
    // 读取输入
    cin >> g >> m >> d >> k >> v;
    
    // 计算列车到达车站所需的时间
    long double t = (m - g) / v;
    
    // 情况1: 高桥即使全程冲刺也无法在冲刺时间内到达车站
    if (g > k * d)
    {
        // 冲刺k秒后,剩余距离(g - k*d)以正常速度1走完
        // 总时间 = 冲刺时间k + 正常行走时间(g - k*d)
        if ((k + (g - k * d)) <= t)
        {
            cout << "Yes";
        }
        else
        {
            cout << "No";
        }
    }
    // 情况2: 高桥可以在冲刺时间内到达车站
    else
    {
        // 计算全程冲刺到达车站所需的时间
        if (g / d <= t)
        {
            cout << "Yes";
        }
        else
        {
            cout << "No";
        }
    }
    
    return 0;
}

【运行结果】

10 30 3 2 1
Yes

D - Round-Trip Delivery

【题目来源】

AtCoder:D - Round-Trip Delivery

【题目描述】

Takahashi works part-time at a delivery company. There are \(N\) delivery hubs in this area, numbered from \(1\) to \(N\).
高桥在一家快递公司兼职。这个地区有 \(N\) 个配送中心,编号从 \(1\)\(N\)

There are \(M\) roads in this area, and the \(i\)-th road connects hub \(A_i\) and hub \(B_i\) bidirectionally. Traveling along this road takes \(C_i\) minutes in either direction.
这个地区有 \(M\) 条道路,第 \(i\) 条道路双向连接配送中心 \(A_i\)\(B_i\)。沿这条道路行驶,无论哪个方向都需要 \(C_i\) 分钟。

Today, Takahashi must depart from hub \(1\), where the headquarters is located, deliver a package to a customer at hub \(T\), and then return to hub \(1\).
今天,高桥必须从总部所在的配送中心 \(1\) 出发,将包裹递送给位于配送中心 \(T\) 的客户,然后返回配送中心 \(1\)

Specifically, Takahashi starts at hub \(1\), travels along roads in sequence, visits hub \(T\) at least once during the journey, and ultimately returns to hub \(1\). He may pass through other hubs along the way, and he is allowed to traverse the same road or visit the same hub multiple times. If the same road is traversed multiple times, the travel time for that road is added each time it is traversed.
具体来说,高桥从配送中心 \(1\) 出发,依次沿道路行驶,在行程中至少访问配送中心 \(T\) 一次,最终返回配送中心 \(1\)。他可以沿途经过其他配送中心,并且允许重复经过同一条道路或多次访问同一个配送中心。如果同一条道路被多次经过,每次经过时都需要累加该道路的行驶时间。

Find the minimum possible total travel time of the roads traversed from the time Takahashi departs hub \(1\) until he returns to hub \(1\).
求高桥从配送中心 \(1\) 出发到返回配送中心 \(1\) 为止,所经过道路的最小可能总行驶时间。

If no valid route exists (a route that departs from hub \(1\), visits hub \(T\) at least once, and returns to hub \(1\), output -1.
如果不存在有效的路线(一条从配送中心 \(1\) 出发,至少访问配送中心 \(T\) 一次,并返回配送中心 \(1\) 的路线),则输出 -1。

【输入】

\(N\) \(M\) \(T\)
\(A_1\) \(B_1\) \(C_1\)
\(A_2\) \(B_2\) \(C_2\)
\(\vdots\)
\(A_M\) \(B_M\) \(C_M\)

  • The first line contains the number of hubs \(N\), the number of roads \(M\), and the hub number \(T\) that must be visited, separated by spaces.
  • The \(i\)-th of the following \(M\) lines contains the numbers of the two hubs \(A_i\), \(B_i\) connected by the \(i\)-th road, and the time \(C_i\) required to travel along that road, separated by spaces.

【输出】

Output in one line the minimum total time for Takahashi to depart from hub \(1\), visit hub \(T\) at least once, and return to hub \(1\). If no valid route exists, output -1.

【输入样例】

4 4 3
1 2 5
2 3 3
3 4 2
1 4 10

【输出样例】

16

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005, M = 200005 * 2, INF = 1e18;
int n, m, t;  // n: 节点数,m: 边数,t: 目标节点
int h[N], e[M], w[M], ne[M], idx;  // 邻接表存储图
int dist[N];  // 从起点到各节点的最短距离
bool st[N];  // 节点是否已确定最短距离
typedef pair<int, int> PII;  // 存储(距离, 节点编号)
priority_queue<PII, vector<PII>, greater<PII> > heap;  // 最小堆

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

// Dijkstra算法求最短路径
void dijkstra()
{
    for (int i = 1; i <= n; i++)  // 初始化距离为无穷大
    {
        dist[i] = INF;
    }
    dist[1] = 0;  // 起点距离为0
    heap.push({0, 1});  // 将起点加入堆
    
    while (!heap.empty())
    {
        auto t = heap.top();  // 取出当前距离最小的节点
        heap.pop();
        int veid = t.second, distance = t.first;  // 节点编号和距离
        
        if (st[veid] == true)  // 如果已处理过,跳过
        {
            continue;
        }
        st[veid] = true;  // 标记为已处理
        
        for (int i = h[veid]; i != -1; i = ne[i])  // 遍历邻接节点
        {
            int j = e[i];
            if (dist[j] > distance + w[i])  // 如果找到更短路径
            {
                dist[j] = distance + w[i];  // 更新距离
                heap.push({dist[j], j});  // 加入堆
            }
        }
    }
}

signed main()
{
    cin >> n >> m >> t;  // 读入节点数、边数、目标节点
    memset(h, -1, sizeof(h));  // 初始化邻接表头指针
    
    while (m--)  // 读入边
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);  // 添加无向边
    }
    
    dijkstra();  // 计算从节点1到所有节点的最短距离
    
    if (dist[t] >= INF / 2)  // 如果目标节点不可达(注意使用>=INF/2判断)
    {
        cout << -1 << endl;
    }
    else
    {
        cout << 2 * dist[t] << endl;  // 输出往返距离的2倍
    }
    
    return 0;
}

【运行结果】

4 4 3
1 2 5
2 3 3
3 4 2
1 4 10
16

E - Flowerbed Watering Management

【题目来源】

AtCoder:E - Flowerbed Watering Management

【题目描述】

Takahashi manages \(N\) flower beds arranged in a horizontal row. Each flower bed is numbered from \(1\) to \(N\), and flower bed \(i\) initially stores \(C_i\) liters of water.
高桥管理着 \(N\) 个水平排列的花坛。每个花坛编号从 \(1\)\(N\),花坛 \(i\) 初始储水量为 \(C_i\) 升。

Takahashi will perform \(Q\) operations in order. Each operation is performed on the state resulting from all previous operations. There are \(2\) types of operations:
高桥将按顺序执行 \(Q\) 次操作。每次操作都是在之前所有操作的结果状态上进行的。操作有两种类型:

  • Operation \(1\) (Watering): 1 l r v — Add \(v\) liters of water to each flower bed with a number from \(l\) to \(r\), inclusive.
    操作 1(浇水):1 l r v — 向编号从 \(l\)\(r\)(包含两端)的每个花坛添加 \(v\) 升水。
  • Operation \(2\) (Query): 2 l r — Output the total amount of water stored across all flower beds with numbers from \(l\) to \(r\), inclusive.
    操作 2(查询):2 l r — 输出编号从 \(l\)\(r\)(包含两端)的所有花坛的储水总量。

Find the answers to all operation \(2\) queries in the order they are given.
按给定顺序找出所有操作 \(2\) 查询的答案。

【输入】

\(N\) \(Q\)
\(C_1\) \(C_2\) \(\ldots\) \(C_N\)
\(\text{query}_1\)
\(\text{query}_2\)
\(\vdots\)
\(\text{query}_Q\)

Each \(\text{query}_j\) \((1 \leq j \leq Q)\) is given in one of the following formats:

1 l r v
2 l r
  • The first line contains an integer \(N\) representing the number of flower beds and an integer \(Q\) representing the number of operations, separated by a space.
  • The second line contains integers \(C_1, C_2, \ldots, C_N\) representing the initial amount of water in each flower bed, separated by spaces.
  • Each of the following \(Q\) lines contains one operation.
  • For operation \(1\), it is given in the format 1 l r v, consisting of \(4\) integers separated by spaces: the operation type, the left endpoint \(l\) of the range, the right endpoint \(r\) of the range, and the amount of water \(v\) to add.
  • For operation \(2\), it is given in the format 2 l r, consisting of \(3\) integers separated by spaces: the operation type, the left endpoint \(l\) of the range, and the right endpoint \(r\) of the range.

【输出】

Each time an operation \(2\) is given, output the total amount of water stored in the flower beds with numbers from \(l\) to \(r\), inclusive, at that point in time, on a single line. Output the results in the order the operations are given.

【输入样例】

5 4
3 1 4 1 5
2 1 5
1 2 4 3
2 2 4
2 1 5

【输出样例】

14
15
23

【解题思路】

image

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
int n, q;  // n: 数组长度,q: 操作次数
int w[N];  // 原始数组
struct Node
{
    int l, r;  // 节点代表的区间[l, r]
    int dt, sum;  // dt: 懒标记,sum: 区间和
}tr[N * 4];  // 线段树节点数组

// 上传操作:用子节点信息更新父节点
void pushup(int u)  // 由子节点的信息,来计算父节点的信息
{
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;  // 区间和 = 左子树和 + 右子树和
}

// 下传懒标记
void pushdown(int u)
{
    auto &root = tr[u], &l = tr[u << 1], &r = tr[u << 1 | 1];
    l.dt += root.dt, l.sum += root.dt * (l.r - l.l + 1);  // 更新左子树懒标记和区间和
    r.dt += root.dt, r.sum += root.dt * (r.r - r.l + 1);  // 更新右子树懒标记和区间和
    root.dt = 0;  // 清空当前节点懒标记
}

// 构建线段树
void build(int u, int l, int r)
{
    if (l == r)  // 叶节点
    {
        tr[u] = {l, r, 0, w[l]};
    }
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

// 区间更新
void update(int u, int l, int r, int d)
{
    if (tr[u].l >= l && tr[u].r <= r)  // 当前节点区间完全在更新区间内
    {
        tr[u].dt += d, tr[u].sum += d * (tr[u].r - tr[u].l + 1);  // 更新懒标记和区间和
    }
    else
    {
        pushdown(u);  // 下传懒标记
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid)
        {
            update(u << 1, l, r, d);
        }
        if (r > mid)
        {
            update(u << 1 | 1, l, r, d);
        }
        pushup(u);  // 上传更新
    }
}

// 区间查询
int query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r)  // 当前节点区间完全在查询区间内
    {
        return tr[u].sum;
    }
    else
    {
        pushdown(u);  // 下传懒标记
        int mid = tr[u].l + tr[u].r >> 1;
        int res = 0;  // 初始化结果为0
        if (l <= mid)
        {
            res += query(u << 1, l, r);
        }
        if (r > mid)
        {
            res += query(u << 1 | 1, l, r);
        }
        return res;
    }
}

signed main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
    {
        cin >> w[i];
    }
    build(1, 1, n);  // 构建线段树
    
    while (q--)
    {
        int op; 
        cin >> op;  // 操作类型
        if (op == 1)  // 区间更新
        {
            int l, r, v;
            cin >> l >> r >> v;
            update(1, l, r, v);
        }
        else  // 区间查询
        {
            int l, r; 
            cin >> l >> r;
            cout << query(1, l, r) << endl;
        }
    }
    return 0;
}

【运行结果】

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