题目链接点这里
这场 div3 F 题的算法很基础,但是我此前居然完全没接触过。(芙莉莲震惊.jpg)
不过这下能够算法沙漠面积--
了。
CF1921A Square
1
2
3
4
5
6
7
8
9
10
11
12
13
void solve()
{
int x1 = 1e9, y1 = 1e9, x2 = -1e9, y2 = -1e9, x, y;
for (int i = 1; i <= 4; ++i)
{
cin >> x >> y;
x1 = min(x, x1);
y1 = min(y, y1);
x2 = max(x, x2);
y2 = max(y, y2);
}
cout << (x2 - x1) * (y2 - y1) << endl;
}
CF1921B Arranging Cats
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void solve()
{
int n;
cin >> n;
string s1, s2;
cin >> s1 >> s2;
int diff = 0, ans = 0;
for (int i = 0; i < n; ++i)
{
if (s1[i] == '0' && s2[i] == '1')
{
if (diff < 0)
{
++ans;
++diff;
}
else
{
++diff;
}
}
else if (s1[i] == '1' && s2[i] == '0')
{
if (diff > 0)
{
++ans;
--diff;
}
else
{
--diff;
}
}
}
cout << ans + abs(diff) << endl;
}
CF1921C Sending Messages
每次发信息前都贪心的进行抉择,选最优的方案。若最优的方案都无法满足则 NO
,否则 YES
。注意数数数清楚。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void solve()
{
ll n, f, a, b, m;
cin >> n >> f >> a >> b;
ll last = 0, sumi = 0;
for (int i = 1; i <= n; ++i)
{
cin >> m;
if (i == 1)
{
if ((m - last) * a >= b)
sumi += b;
else
sumi += (m - last) * a;
last = m;
continue;
}
if ((m - last) * a >= b)
sumi += b;
else
sumi += (m - last) * a;
last = m;
}
if (sumi < f)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
CF1921D Very Different Array
容易想到将数组排序并翻转,从而尽量将大数和小数匹配。接着贪心的从 $brr$ 的两端选出绝对值之差更大的数,直到已选了出 $n$ 个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void solve()
{
ll n, m, ans = 0;
cin >> n >> m;
vector<ll> arr(n), brr(m);
for (int i = 0; i < n; ++i)
cin >> arr[i];
for (int i = 0; i < m; ++i)
cin >> brr[i];
sort(all(arr));
sort(all(brr));
reverse(all(brr));
int l = 0, r = m - 1, cl = 0, cr = n - 1, cnt = 0;
while (cl <= cr && cnt <= n)
{
if (abs(brr[l] - arr[cl]) >= abs(brr[r] - arr[cr]))
{
ans += abs(brr[l] - arr[cl]);
++l, ++cl;
}
else
{
ans += abs(brr[r] - arr[cr]);
--r, --cr;
}
}
cout << ans << endl;
}
CF1921E Eat the Chip
$x_1 \ge x_2$ 的时候不会发生相遇,是平局。然后考虑 $x_1 \le x_2$。当 $step$ 为偶数时,只会发生 Alice 赢或平局的情况。因为数据范围不大,这时可以暴力模拟每一步,并令 Bob 逃离 Alice,Alice 追赶 Bob。最后看是否追上即可判断结果。$step$ 为奇数的讨论同上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void solve()
{
ll h, w, x1, y1, x2, y2;
cin >> h >> w >> x1 >> y1 >> x2 >> y2;
ll step = abs(x2 - x1 - 1);
if (x1 >= x2)
{
cout << "Draw" << endl;
}
else if (step % 2 == 0)
{
for (int i = 1; i <= step; ++i)
{
if (i % 2 == 1)
{
if (y2 > y1)
++y1;
else if (y2 < y1)
--y1;
}
else if (i % 2 == 0)
{
if (y2 > y1 && y2 < w)
++y2;
else if (y2 < y1 && y2 > 1)
--y2;
}
}
if (abs(y2 - y1) <= 1)
cout << "Alice" << endl;
else
cout << "Draw" << endl;
}
else
{
for (int i = 1; i <= step; ++i)
{
if (i % 2 == 1)
{
if (y2 > y1 && y1 > 1)
--y1;
else if (y2 < y1 && y1 < w)
++y1;
}
else if (i % 2 == 0)
{
if (y2 > y1)
--y2;
else if (y2 < y1)
++y2;
}
}
if (abs(y2 - y1) <= 1)
cout << "Bob" << endl;
else
cout << "Draw" << endl;
}
}
CF1921F Sum of Progression
这题用到下面两个算法。
-
带权前缀和
$sum_{l-1}=a_1+2 \times a_2+3 \times a_3+…+(l-1) \times a_{l-1}$
$sum_{r}=a_1+2 \times a_2+3\times a_3+…+l \times a_l+…+r \times a_r$
$sum_{r}-sum_{l-1}=l \times a_l+…+r \times a_r=(l-1) \times (a_l+…+a_r)+a_l+…+a_r$
-
根号分治
找到两种算法,复杂度分别为 $O(D)$ 与 $O(\frac{n}{D})$ (或者类似的复杂度)。每次根据数据大小选取具体使用的算法。取分界点 $D=\sqrt{n}$,可将复杂度降至 $O(q \times \sqrt{n})$。
这题的带权前缀和按公差分为 $lim$ 组,分别进行预处理。分界点可取 $200$,大于两百的数据暴力求解,小于两百的数据用带权前缀和直接计算答案。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
int n, q, lim = 200;
vector<vector<ll>> pre(lim, vector<ll>(1e5 + lim * 2 + 1));
vector<vector<ll>> sumi(lim, vector<ll>(1e5 + lim * 2 + 1));
void solve()
{
cin >> n >> q;
vector<ll> arr(n + 1);
for (int i = 0; i < n; ++i)
cin >> arr[i];
for (int d = 1; d < lim; ++d)
for (int i = 0; i < n; ++i)
{
pre[d][i + d] = pre[d][i] + arr[i];
sumi[d][i + d] = sumi[d][i] + arr[i] * (i / d + 1);
}
while (q--)
{
ll s, d, k;
cin >> s >> d >> k;
--s;
if (d < lim)
{
int r = s + d * k, l = s;
cout << sumi[d][r] - sumi[d][l] - (l / d) * (pre[d][r] - pre[d][l]) << " ";
}
else
{
ll ans = 0;
for (int i = 0; i < k; ++i)
ans += arr[i * d + s] * (i + 1);
cout << ans << " ";
}
}
}