Skip to content

Commit cf4a9ad

Browse files
committed
add abc389
1 parent 3541532 commit cf4a9ad

File tree

3 files changed

+375
-0
lines changed

3 files changed

+375
-0
lines changed

docs/algorithm/AtCoder/abc389.md

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
## [A - 9x9](https://atcoder.jp/contests/abc389/tasks/abc389_a)
2+
3+
???+ Abstract "题目大意"
4+
5+
给你一个长度为 $3$ 的字符串,第 $1$ 位和第 $3$ 位是数字,第 $2$ 位是乘法符号 $\times$,输出这个算式的结果。
6+
7+
??? Success "参考代码"
8+
9+
=== "C++"
10+
11+
```c++
12+
#include <iostream>
13+
14+
using namespace std;
15+
16+
int main()
17+
{
18+
string s;
19+
cin >> s;
20+
cout << (s[0] - '0') * (s[2] - '0') << endl;
21+
return 0;
22+
}
23+
```
24+
25+
---
26+
27+
## [B - tcaF](https://atcoder.jp/contests/abc389/tasks/abc389_b)
28+
29+
???+ Abstract "题目大意"
30+
31+
给你一个正整数 $X(2 \le X \le 3 \times 10 ^ {18})$,找到一个正整数 $N$ 使得 $N! = X$,保证答案一定存在。
32+
33+
??? Success "参考代码"
34+
35+
=== "C++"
36+
37+
```c++
38+
#include <iostream>
39+
40+
using namespace std;
41+
using ULL = unsigned long long;
42+
43+
int main()
44+
{
45+
ULL x, num = 1;
46+
cin >> x;
47+
for(; x != num; num++)
48+
x /= num;
49+
cout << num << endl;
50+
return 0;
51+
}
52+
```
53+
54+
---
55+
56+
## [C - Snake Queue](https://atcoder.jp/contests/abc389/tasks/abc389_c)
57+
58+
???+ Abstract "题目大意"
59+
60+
有一个蛇的队列,你需要处理 $Q$ 个询问:
61+
62+
- `1 l`,队列中加入一条长度为 $l$ 的蛇。每一条蛇有头坐标和尾坐标。尾坐标等于头坐标加上自身的长度。如果当前队列为空,则新加入的蛇的头坐标为 $0$。如果队列不为空,则新加入的蛇的头坐标等于队列中最后一条蛇的尾坐标。
63+
- `2`:队列中第一条蛇出队。
64+
- `3 k`:输出第 $k$ 条蛇的头坐标。
65+
66+
??? Note "解题思路"
67+
68+
维护队列的前缀和就好。
69+
70+
??? Success "参考代码"
71+
72+
=== "C++"
73+
74+
```c++
75+
#include <iostream>
76+
#include <vector>
77+
78+
using namespace std;
79+
using LL = long long;
80+
81+
int main()
82+
{
83+
int q;
84+
cin >> q;
85+
vector<LL> a = {0}, s = {0};
86+
int head = 1;
87+
while(q--)
88+
{
89+
int op;
90+
cin >> op;
91+
if(op == 1)
92+
{
93+
int l;
94+
cin >> l;
95+
a.push_back(l);
96+
s.push_back(l + s.back());
97+
}
98+
else if(op == 2)
99+
head++;
100+
else
101+
{
102+
int k;
103+
cin >> k;
104+
cout << s[head + k - 2] - s[head - 1] << endl;
105+
}
106+
}
107+
return 0;
108+
}
109+
```
110+
111+
---
112+
113+
## [D - Squares in Circle](https://atcoder.jp/contests/abc389/tasks/abc389_d)
114+
115+
???+ Abstract "题目大意"
116+
117+
有一个二维的平面,划分成多个 $1 \times 1$ 的网格。如果在原点画一个半径为 $R(1 \le R \le 10 ^ 6)$ 的圆,有多少个网格会被这个圆完整的包含?
118+
119+
??? Note "解题思路"
120+
121+
$R \le 10 ^ 6$,直接枚举就好。
122+
123+
??? Success "参考代码"
124+
125+
=== "C++"
126+
127+
```c++
128+
#include <cmath>
129+
#include <iostream>
130+
131+
using namespace std;
132+
using LL = long long;
133+
134+
int main()
135+
{
136+
auto sq = [](double x) -> double
137+
{ return x * x; };
138+
139+
double r;
140+
cin >> r;
141+
double rr = r * r;
142+
LL ans = 0;
143+
for(double y = 0.5, yy = sq(y); 0.25 + yy <= rr; y += 1, yy = sq(y))
144+
{
145+
double x = sqrt(rr - yy);
146+
int j = floor(x - 0.5);
147+
int cnt = 2 * j + 1;
148+
ans += cnt;
149+
if(y > 1)
150+
ans += cnt;
151+
}
152+
cout << ans << endl;
153+
return 0;
154+
}
155+
```
156+
157+
---
158+
159+
## [E - Square Price](https://atcoder.jp/contests/abc389/tasks/abc389_e)
160+
161+
???+ Abstract "题目大意"
162+
163+
有 $N(2 \le N \le 10 ^ 5)$ 种商品,每种商品都有无限个。购买 $k$ 个第 $i$ 种商品的价格为 $k^2P_i$ 元,其中 $1 \le P_i \le 2 \times 10^ 9$ 。你有 $M(1 \le M \le 10 ^ {18})$ 元,最多能买多少个商品?
164+
165+
??? Note "解题思路"
166+
167+
可以发现,第 $i$ 种商品的第 $k$ 个的价格实际是 $(k^2 - (k-1)^2)P_i = (2k-1)P_i$
168+
169+
这里如果用优先队列一个一个买的话会超时,但实际上可以二分 $X$ 元以内的商品能不能全部买完,时间复杂度为 $O(N\log m)$。
170+
171+
注意这题 $k^2P_i$ 会爆 `long long`,需要开 `__int128`。
172+
173+
??? Success "参考代码"
174+
175+
=== "C++"
176+
177+
```c++
178+
#include <iostream>
179+
#include <vector>
180+
181+
using namespace std;
182+
using LL = long long;
183+
using i128 = __int128;
184+
185+
int main()
186+
{
187+
int n;
188+
LL m;
189+
cin >> n >> m;
190+
vector<LL> p(n);
191+
for (auto &x : p)
192+
cin >> x;
193+
194+
auto check = [&p, m](LL x) -> bool
195+
{
196+
i128 sum = m;
197+
for (auto pi : p)
198+
{
199+
i128 k = (x + pi) / (2 * pi);
200+
sum -= k * k * pi;
201+
if (sum < 0)
202+
return false;
203+
}
204+
return true;
205+
};
206+
207+
LL l = 0, r = m;
208+
while (l < r)
209+
{
210+
LL mid = (l + r + 1) / 2;
211+
if (check(mid))
212+
l = mid;
213+
else
214+
r = mid - 1;
215+
}
216+
LL ans = 0;
217+
for (auto pi : p)
218+
{
219+
LL k = (l + pi) / (2 * pi);
220+
ans += k;
221+
m -= k * k * pi;
222+
}
223+
ans += m / (l + 1);
224+
cout << ans << endl;
225+
return 0;
226+
}
227+
```
228+
229+
---
230+
231+
## [F - Rated Range](https://atcoder.jp/contests/abc389/tasks/abc389_f)
232+
233+
???+ Abstract "题目大意"
234+
235+
你打算参加 $N(1 \le N \le 2 \times 10^5)$ 场比赛,如果在第 $i$ 场比赛开始前你的分数在闭区间 $[L_i, R_i]$ 中($1 \le L_i \le R_i \le 5 \times 10^5$),比赛结束后分数会增加 $1$。
236+
237+
有 $Q(1 \le Q \le 3 \times 10^5)$ 个询问,每个询问给你一个整数 $X(1 \le X \le 5 \times 10^5)$,你需要回答如果初始的分数是 $X$,在参加完这 $N$ 场比赛之后分数是多少。
238+
239+
??? Note "解题思路"
240+
241+
设 $F(x)$ 表示初始分数为 $x$ 经过 $N$ 场比赛之后的分数。不难发现 $F(x)$ 是单调递增的。这是因为分数是一分一分的加的,所以对于 $x \le y$,至多有 $F(x) = F(y)$。
242+
243+
于是考虑将 $Q$ 个询问按照初始分数排序,然后用线段树维护,显然,无论经过多少场比赛,线段树的值也是单调的,某一场比赛就相当于是给 $[L_i, R_i]$ 中的值 $+1$。在线段树节点中维护区间的最大最小值,就可以出对应的区间进行修改。时间复杂度为 $O(N\log Q)$。
244+
245+
??? Success "参考代码"
246+
247+
=== "C++"
248+
249+
```c++
250+
#include <algorithm>
251+
#include <iostream>
252+
#include <unordered_map>
253+
#include <utility>
254+
#include <vector>
255+
256+
using namespace std;
257+
258+
class SegTree
259+
{
260+
public:
261+
SegTree(const vector<int> &a) : n(a.size() - 1), t(4 * n)
262+
{
263+
auto build = [&](auto &self, int p, int beg, int end) -> void
264+
{
265+
if (beg == end)
266+
{
267+
t[p].min_val = t[p].max_val = a[beg];
268+
return;
269+
}
270+
int lch = 2 * p, rch = 2 * p + 1;
271+
int mid = (beg + end) / 2;
272+
self(self, lch, beg, mid);
273+
self(self, rch, mid + 1, end);
274+
push_up(p);
275+
};
276+
277+
build(build, 1, 1, n);
278+
}
279+
280+
void update(int l, int r) { add(1, 1, n, l, r); }
281+
282+
int ask(int pos) { return at(1, 1, n, pos); }
283+
284+
private:
285+
struct Node
286+
{
287+
int min_val, max_val, add;
288+
};
289+
290+
int n;
291+
vector<Node> t;
292+
293+
void push_up(int p)
294+
{
295+
int lch = p * 2, rch = p * 2 + 1;
296+
t[p].min_val = t[lch].min_val;
297+
t[p].max_val = t[rch].max_val;
298+
}
299+
300+
void push_down(int p)
301+
{
302+
auto add_lazy = [&](int p, int add) -> void
303+
{
304+
t[p].max_val += add;
305+
t[p].min_val += add;
306+
t[p].add += add;
307+
};
308+
309+
int lch = p * 2, rch = p * 2 + 1;
310+
add_lazy(lch, t[p].add);
311+
add_lazy(rch, t[p].add);
312+
t[p].add = 0;
313+
}
314+
315+
void add(int p, int beg, int end, int l, int r)
316+
{
317+
if (t[p].max_val < l || t[p].min_val > r)
318+
return;
319+
if (t[p].min_val >= l && t[p].max_val <= r)
320+
{
321+
t[p].min_val++;
322+
t[p].max_val++;
323+
t[p].add++;
324+
return;
325+
}
326+
push_down(p);
327+
int lch = 2 * p, rch = 2 * p + 1;
328+
int mid = (beg + end) / 2;
329+
add(lch, beg, mid, l, r);
330+
add(rch, mid + 1, end, l, r);
331+
push_up(p);
332+
}
333+
334+
int at(int p, int beg, int end, int pos)
335+
{
336+
if (beg == end)
337+
return t[p].max_val;
338+
push_down(p);
339+
int lch = 2 * p, rch = 2 * p + 1;
340+
int mid = (beg + end) / 2;
341+
return pos <= mid ? at(lch, beg, mid, pos) : at(rch, mid + 1, end, pos);
342+
}
343+
};
344+
345+
int main()
346+
{
347+
int n;
348+
cin >> n;
349+
vector<pair<int, int>> contests(n);
350+
for (auto &[l, r] : contests)
351+
cin >> l >> r;
352+
int q;
353+
cin >> q;
354+
vector<int> a(q + 1);
355+
for (int i = 1; i <= q; i++)
356+
cin >> a[i];
357+
vector<int> b = a;
358+
sort(b.begin(), b.end());
359+
unordered_map<int, int> pos;
360+
for (int i = 1; i <= q; i++)
361+
pos[b[i]] = i;
362+
SegTree t(b);
363+
for (auto [l, r] : contests)
364+
t.update(l, r);
365+
for (int i = 1; i <= q; i++)
366+
{
367+
int x = a[i];
368+
cout << t.ask(pos[x]) << endl;
369+
}
370+
return 0;
371+
}
372+
```
373+

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
1111
最近更新:
1212

13+
- (20250606) [ABC389(A-F) 题解](./algorithm/AtCoder/abc389.md)
1314
- (20250601) [ABC388(A-G) 题解](./algorithm/AtCoder/abc388.md)
1415
- (20250521) [System R 优化器框架精读](./dev/db/optimizer/System_R/SystemR.md)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ nav:
99
- 算法:
1010
- algorithm/index.md
1111
- AtCoder:
12+
- ABC389(A-F): algorithm/AtCoder/abc389.md
1213
- ABC388(A-G): algorithm/AtCoder/abc388.md
1314
- ABC386(A-F): algorithm/AtCoder/abc386.md
1415
- ABC385(A-F): algorithm/AtCoder/abc385.md

0 commit comments

Comments
 (0)