AtCoder Weekday Contest 0036 Beta题解(AWC 0036 Beta A-E)
A - Library Loan Management
【题目来源】
AtCoder:A - Library Loan Management
【题目描述】
Takahashi manages \(N\) libraries in the city. Library \(i\) (\(1 \leq i \leq N\)) has \(M_i\) genres, and each genre is numbered from \(1\) to \(M_i\).
高桥管理着市里的 \(N\) 个图书馆。图书馆 \(i\)(\(1 \leq i \leq N\))有 \(M_i\) 个类别,每个类别编号从 \(1\) 到 \(M_i\)。
The initial number of books in genre \(j\) (\(1 \leq j \leq M_i\)) of library \(i\) is \(S_{i,j}\). It is possible for a genre to have an initial book count of \(0\).
图书馆 \(i\) 的类别 \(j\)(\(1 \leq j \leq M_i\))的初始图书数量为 \(S_{i,j}\)。一个类别的初始图书数量可能为 \(0\)。
One day, Aoki organized the lending records and found that there are \(Q\) unprocessed lending requests recorded in order. Takahashi will process these requests sequentially from the \(1\)-st to the \(Q\)-th. The initial book counts represent the number of books at the time before processing these lending requests.
一天,青木整理了借阅记录,发现有 \(Q\) 条未处理的借阅请求按顺序记录。高桥将按顺序从第 \(1\) 条到第 \(Q\) 条处理这些请求。初始图书数量表示在处理这些借阅请求之前馆内的图书数量。
The \(k\)-th lending request (\(1 \leq k \leq Q\)) is "borrow \(1\) book of genre \(d_k\) from library \(v_k\)." Each lending request is processed as follows:
第 \(k\) 条借阅请求(\(1 \leq k \leq Q\))是"从图书馆 \(v_k\) 借出 \(1\) 本类别 \(d_k\) 的图书"。每条借阅请求按如下方式处理:
- If the current number of books of genre \(d_k\) in library \(v_k\) is \(1\) or more, the lending succeeds, and the number of books of that genre decreases by \(1\).
如果图书馆 \(v_k\) 的类别 \(d_k\) 的当前图书数量大于等于 \(1\),则借阅成功,该类别图书数量减少 \(1\)。 - If the current number of books of genre \(d_k\) in library \(v_k\) is \(0\), the lending fails, and the number of books does not change.
如果图书馆 \(v_k\) 的类别 \(d_k\) 的当前图书数量为 \(0\),则借阅失败,图书数量不变。
After processing all lending requests from the \(1\)-st to the \(Q\)-th in order, output the remaining number of books for each genre in each library, and the number of requests that failed.
按顺序处理完从第 \(1\) 条到第 \(Q\) 条的所有借阅请求后,输出每个图书馆每个类别的剩余图书数量,以及失败的请求数量。
【输入】
\(N\)
\(M_1\) \(S_{1,1}\) \(S_{1,2}\) \(\ldots\) \(S_{1,M_1}\)
\(M_2\) \(S_{2,1}\) \(S_{2,2}\) \(\ldots\) \(S_{2,M_2}\)
\(\vdots\)
\(M_N\) \(S_{N,1}\) \(S_{N,2}\) \(\ldots\) \(S_{N,M_N}\)
\(Q\)
\(v_1\) \(d_1\)
\(v_2\) \(d_2\)
\(\vdots\)
\(v_Q\) \(d_Q\)
- The first line contains an integer \(N\) representing the number of libraries.
- Among the following \(N\) lines, the \(i\)-th line (\(1 \leq i \leq N\)) contains the number of genres \(M_i\) in library \(i\) and the initial book counts \(S_{i,1}, S_{i,2}, \ldots, S_{i,M_i}\) for each genre, given in this order separated by spaces.
- The next line contains an integer \(Q\) representing the number of lending requests.
- Among the following \(Q\) lines, the \(k\)-th line (\(1 \leq k \leq Q\)) contains the library number \(v_k\) and the genre number \(d_k\) for the \(k\)-th lending request, separated by a space.
【输出】
Output \(N + 1\) lines.
- On the \(i\)-th line (\(1 \leq i \leq N\)), output the remaining number of books for each genre of library \(i\) after processing all lending requests, as \(M_i\) integers in order from genre \(1\) to genre \(M_i\), separated by spaces.
- On the \((N + 1)\)-th line, output the number of failed lending requests as a single integer.
【输入样例】
2
2 3 1
1 0
4
1 1
1 2
1 2
2 1
【输出样例】
2 0
0
2
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, m[N], q, cnt; // n: 货架数, m: 每个货架的商品数, q: 操作数, cnt: 缺货次数
int s[N][N]; // 货架库存矩阵
int main()
{
cin >> n; // 输入货架数量
for (int i = 1; i <= n; i++) // 输入每个货架的库存
{
cin >> m[i]; // 第i个货架的商品种类数
for (int j = 1; j <= m[i]; j++) // 输入每种商品的库存
{
cin >> s[i][j];
}
}
cin >> q; // 输入操作次数
while (q--) // 处理每次操作
{
int u, d;
cin >> u >> d; // 货架编号和商品编号
if (s[u][d] >= 1) // 如果有库存
{
s[u][d]--; // 售出一件
}
else
{
cnt++; // 缺货,记录缺货次数
}
}
for (int i = 1; i <= n; i++) // 输出最终库存
{
for (int j = 1; j <= m[i]; j++)
{
cout << s[i][j] << " ";
}
cout << endl;
}
cout << cnt << endl; // 输出缺货次数
return 0;
}
【运行结果】
2
2 3 1
1 0
4
1 1
1 2
1 2
2 1
2 0
0
2
B - Managing the Guest List
【题目来源】
AtCoder:B - Managing the Guest List
【题目描述】
Takahashi has been assigned as the receptionist for a large party.
高桥被任命为一场大型派对的接待员。
Invited guests arrive at the party one after another. Each guest is assigned a guest number, which is an integer between \(1\) and \(10^9\) inclusive, and different guests are assigned different numbers. Takahashi records each arriving person on the guest list. He may also receive inquiries from the venue staff asking, "Has this person already arrived?"
受邀客人陆续到达派对。每位客人被分配了一个嘉宾编号,这是一个介于 \(1\) 到 \(10^9\) 之间的整数,不同的客人分配不同的编号。高桥在嘉宾名单上记录每位到达的人。他也可能收到现场工作人员的询问:“这个人已经到达了吗?”
The guest list is initially empty.
嘉宾名单初始为空。
Takahashi performs \(Q\) operations in order. The \(i\)-th operation is represented by a pair of type \(T_i\) and guest number \(X_i\), and is one of the following two types:
高桥按顺序执行 \(Q\) 次操作。第 \(i\) 次操作由一个类型 \(T_i\) 和嘉宾编号 \(X_i\) 组成,是以下两种类型之一:
- \(T_i = 1\) (Record arrival) : Add the person with guest number \(X_i\) to the guest list. It is guaranteed that \(X_i\) is not already in the guest list at the time this operation is performed.
\(T_i = 1\) (记录到达) :将嘉宾编号为 \(X_i\) 的人添加到嘉宾名单中。保证在执行此操作时,\(X_i\) 尚未在嘉宾名单中。 - \(T_i = 2\) (Arrival inquiry) : Check whether the person with guest number \(X_i\) is currently in the guest list.
\(T_i = 2\) (到达查询) :检查嘉宾编号为 \(X_i\) 的人当前是否在嘉宾名单中。
For each operation where \(T_i = 2\), determine whether the person with the specified guest number is in the guest list.
对于每个 \(T_i = 2\) 的操作,判断指定嘉宾编号的人是否在嘉宾名单中。
【输入】
\(Q\)
\(T_1\) \(X_1\)
\(T_2\) \(X_2\)
\(\vdots\)
\(T_Q\) \(X_Q\)
The first line contains an integer \(Q\) representing the number of operations.
Of the following \(Q\) lines, the \(i\)-th line \((1 \leq i \leq Q)\) contains an integer \(T_i\) representing the type of the \(i\)-th operation and an integer \(X_i\) representing the guest number, separated by a space.
【输出】
For each operation where \(T_i = 2\), output the result on a separate line in the order the operations are performed.
If the person with guest number \(X_i\) is in the guest list at that time, output Yes; otherwise, output No.
【输入样例】
5
1 10
2 10
2 3
1 3
2 3
【输出样例】
Yes
No
Yes
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int q; // 操作次数
map<int, int> mp; // 使用map作为集合
int main()
{
cin >> q; // 输入操作次数
while (q--) // 处理每次操作
{
int t, x;
cin >> t >> x; // 输入操作类型和数值
if (t == 1) // 插入操作
{
mp[x] = 1; // 将x插入集合
}
else // 查询操作
{
if (mp[x]) // 如果x存在于集合中
{
cout << "Yes\n";
}
else
{
cout << "No\n";
}
}
}
return 0;
}
【运行结果】
5
1 10
2 10
Yes
2 3
No
1 3
2 3
Yes
C - Splitting Logs
【题目来源】
AtCoder:C - Splitting Logs
【题目描述】
Takahashi has a log consisting of \(N\) parts connected in a row. The parts are numbered \(1, 2, \ldots, N\) from left to right, and the length of part \(i\) is \(A_i\).
高桥有一根由 \(N\) 个部分连接而成的木头。这些部分从左到右编号为 \(1, 2, \ldots, N\),第 \(i\) 部分的长度为 \(A_i\)。
There are boundaries between adjacent parts, and there are \(N - 1\) such boundaries. Namely, the boundary between part \(i\) and part \(i + 1\) \((1 \leq i \leq N - 1)\). Takahashi chooses \(K\) of these boundaries to cut, dividing the log into \(K + 1\) fragments.
相邻部分之间存在边界,共有 \(N - 1\) 个这样的边界。具体而言,第 \(i\) 部分与第 \(i + 1\) 部分之间的边界(\(1 \leq i \leq N - 1\))。高桥选择其中的 \(K\) 个边界进行切割,将木头分成 \(K + 1\) 段。
The length of each fragment is determined by the sum of the lengths of the parts contained in that fragment. Let \(M\) be the maximum length among the \(K + 1\) fragments.
每段的长度由该段包含的各部分长度之和决定。设 \(M\) 为这 \(K + 1\) 段中的最大长度。
Find the minimum possible value of \(M\) when the cut positions are chosen optimally.
当切割位置被最优选择时,求 \(M\) 的最小可能值。
【输入】
\(N\) \(K\)
\(A_1\) \(A_2\) \(\ldots\) \(A_N\)
- The first line contains an integer \(N\) representing the number of parts and an integer \(K\) representing the number of cuts, separated by a space.
- The second line contains integers \(A_1, A_2, \ldots, A_N\) representing the lengths of the parts, separated by spaces.
【输出】
Print in one line the minimum value of \(M\), the maximum length among the \(K + 1\) fragments, when the cut positions are chosen optimally.
【输入样例】
5 2
3 5 4 7 6
【输出样例】
11
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int n, k; // n: 数组长度, k: 分段数
int a[N], sum; // 数组元素, 总和
// 检查是否能在每个分段和不超过x的情况下分成最多k段
bool check(int x)
{
int cnt = 0, tot = 0; // cnt: 分段数, tot: 当前分段和
for (int i = 1; i <= n; i++)
{
if (tot + a[i] > x) // 如果加上当前元素会超过x
{
cnt++; // 新开一段
tot = a[i]; // 从当前元素开始新的一段
}
else
{
tot += a[i]; // 加入当前分段
}
}
return cnt <= k; // 分段数不超过k
}
signed main()
{
cin >> n >> k; // 输入数组长度和分段数
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum += a[i]; // 计算总和
}
int l = 1, r = sum; // 二分查找最小最大分段和
while (l < r)
{
int mid = (l + r) / 2;
if (check(mid)) // 如果mid可行
{
r = mid; // 尝试更小的值
}
else
{
l = mid + 1; // 需要更大的值
}
}
cout << l << endl; // 输出最小最大分段和
return 0;
}
【运行结果】
5 2
3 5 4 7 6
11
浙公网安备 33010602011771号