Martian148's blog Martian148's blog
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档

Martian148

一只热爱文科的理科生
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档
  • codeforses 题解

  • atcoder 题解

    • AtCoder Beginner Contest 344 A-G 题解
    • AtCoder Beginner Contest 345 A-F 题解
    • AtCoder Beginner Contest 346 A-G 题解
    • AtCoder Beginner Contest 347 A-G 题解
    • AtCoder Beginner Contest 353 A-G 题解
    • AtCoder Beginner Contest 359 A-G 题解
    • AtCoder Beginner Contest 366 A-F 题解
      • A - Election 2
        • Code
      • B - Vertical Writing
        • Code
      • C - Balls and Bag Query
        • Solution
        • Code
      • D - Cuboid Sum Query
        • Solution
        • Code
      • E - Manhattan Multifocal Ellipse
        • Question
        • Solution
        • Code
      • F - Maximum Composition
        • Question
        • Solution
        • Code
    • AtCoder Beginner Contest 369 A-F 题解
  • XCPC 题解

  • 校训练赛题解

  • 牛客题解

  • 蓝桥杯题解

  • 典题选讲

  • 杂题

  • 算法题解
  • atcoder 题解
martian148
2024-08-11
目录

AtCoder Beginner Contest 366 A-F 题解

AtCoder Beginner Contest 366 (opens new window)

# A - Election 2

# Code

#include <bits/stdc++.h>
using namespace std;
int main() {
    int N, A , B ; cin >> N >> A >> B;
    int A_ = N - (A + B) + A;
    if (A_ < B) {
        cout << "Yes" << endl;
        return 0;
    }
    int B_ = N - (A + B) + B;
    if (B_ < A) {
        cout << "Yes" << endl;
        return 0;
    }
    cout << "No" << endl;
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# B - Vertical Writing

# Code

#include <bits/stdc++.h>
using namespace std;
int main() {
    int N; cin >> N;
    vector<string> S(N);
    int M = -1;
    for (int i = 0; i < N; i++) {
        cin >> S[i];
        M = max(M, (int)S[i].size());
    }
    vector<vector<char>> A(N, vector<char>(M, 0));
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < S[i].size(); j++) {
            A[i][j] = S[i][j];
        }
        for (int j = S[i].size(); j < M; j++) {
            A[i][j] = '*';
        }
    }
    for (int j = 0; j < M; j++) {
        for (int i = 0; i < N; i++) {
            if (A[i][j] == '*') A[i][j] = ' ';
            else break;
        }
    }
    for (int j = 0; j < M; j++) {
        for (int i = N - 1; i >= 0; i--) {
            cout << A[i][j];
        }
        cout << endl;
    }
    return 0;
}
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

# C - Balls and Bag Query

# Solution

使用 p 数组记录一个数出现了几次,用 cntcntcnt 维护答案

# Code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int main() {
    int Q; cin >> Q;
    vector<int> p(maxn, 0);
    int cnt = 0;
    while (Q--) {
        int op; cin >> op;
        if (op == 1) {
            int x; cin >> x;
            if (p[x]++ == 0) cnt += 1;
        }
        else if (op == 2) {
            int x; cin >> x;
            if (--p[x] == 0) cnt -= 1;
        }
        else {
            cout << cnt << endl;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# D - Cuboid Sum Query

# Solution

三维容斥

# Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
    ios::sync_with_stdio(0);
    int n; cin >> n;
    vector<vector<vector<int>>> a(n + 1, vector<vector<int>>(n + 1, vector<int>(n + 1, 0)));
    for (int i = 1; i <= n; i++) 
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= n; k++) {
                cin >> a[i][j][k];
            }
    vector<vector<vector<int>>> s(n + 1, vector<vector<int>>(n + 1, vector<int>(n + 1, 0)));
    for (int i = 1; i <= n; i++) 
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= n; k++) {
                s[i][j][k] = s[i - 1][j][k] + s[i][j - 1][k] + s[i][j][k - 1] - s[i - 1][j - 1][k] - s[i - 1][j][k - 1] - s[i][j - 1][k - 1] + s[i - 1][j - 1][k - 1] + a[i][j][k];
            }
    int Q; cin >> Q;
    while (Q--) {
        int x1, y1, z1, x2, y2, z2; cin >> x1 >> x2 >> y1 >> y2 >> z1 >> z2;
        cout << s[x2][y2][z2] - s[x1 - 1][y2][z2] - s[x2][y1 - 1][z2] - s[x2][y2][z1 - 1] + s[x1 - 1][y1 - 1][z2] + s[x1 - 1][y2][z1 - 1] + s[x2][y1 - 1][z1 - 1] - s[x1 - 1][y1 - 1][z1 - 1] << endl;
    }
    return 0;
}
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

# E - Manhattan Multifocal Ellipse

# Question

给定 NNN 个点 (x1,y1),(x2,y2),…,(xN,yN)(x_1, y_1), (x_2, y_2), \dots, (x_N, y_N)(x1​,y1​),(x2​,y2​),…,(xN​,yN​) 在二维平面上,以及非负整数 DDD。

找出满足 ∑i=1N(∣x−xi∣+∣y−yi∣)≤D\displaystyle \sum_{i=1}^N (|x-x_i|+|y-y_i|) \leq Di=1∑N​(∣x−xi​∣+∣y−yi​∣)≤D 的整数对 (x,y)(x, y)(x,y) 的数量。

# Solution

先把 x,yx,yx,y 分开,其实可以独立的来看这个问题

设 f(x)=∑i=1N∣x−xi∣,g(y)=∑i=1N∣y−yi∣f(x)=\sum\limits_{i=1}^N|x-x_i|,g(y)=\sum\limits_{i=1}^N|y-y_i|f(x)=i=1∑N​∣x−xi​∣,g(y)=i=1∑N​∣y−yi​∣,那么答案就是满足 f(x)+g(y)≤Df(x)+g(y) \le Df(x)+g(y)≤D 的 (x,y)(x,y)(x,y) 数对的数量

首先,我们发现值域其实不大,我们需要对序列中的每个 x∈{−(M+D),M+D}x\in\{-(M+D),M+D\}x∈{−(M+D),M+D},都求出其 f(x)f(x)f(x),我们可以用递推来计算,假设我们已知 f(x−1)f(x-1)f(x−1),并且知道比 xxx 小的 xix_ixi​ 有 kkk 个,那么有 kkk 个的距离需要增加 111,有 N−kN-kN−k 个的距离需要减少 111,所以,f(x)=f(x−1)+k−(N−k)=f(x−1)+2×k−Nf(x)=f(x-1)+k-(N-k)=f(x-1)+2\times k-Nf(x)=f(x−1)+k−(N−k)=f(x−1)+2×k−N

同理,我们也能算出 g(y)g(y)g(y)

算出了 f(x),g(y)f(x),g(y)f(x),g(y) 由于是 (x,y)(x,y)(x,y) 是独立的,所以可以把 f(x),g(y)f(x),g(y)f(x),g(y) 都从小到大排序,然后用一种所谓 "尺取法" 的东西(Atcoder题解叫这个,我感觉就是指针)

我们需要满足 f(x)+g(y)≤Df(x)+g(y)\le Df(x)+g(y)≤D,我们把 xxx 从大到小枚举,然后令指针 j=0j=0j=0 指向 g(y)g(y)g(y) 最小的节点,找到满足 f(x)+g(y)≤Df(x)+g(y)\le Df(x)+g(y)≤D 最大的 yj′y_j'yj′​,那么对于这个 xix_ixi​,就有 jjj 个 yyy 满足条件

# Code

N, D = map(int, input().split())
x = [0] * N
y = [0] * N
for i in range(N):
    x[i], y[i] = map(int, input().split())
M = 2 * 10 ** 6


def calc(x):
    xsum = [0] * (2 * M + 1)
    x.sort()
    i = 0
    xsum[-M] = sum(x) + N * M
    for j in range(-M + 1, M + 1):
        while i < N and x[i] < j:
            i += 1
        xsum[j] = xsum[j - 1] + 2 * i - N
    return xsum

xsum = calc(x)
ysum = calc(y)
ans = 0
xsum.sort()
ysum.sort()
j = 0
for i in range(2 * M + 1)[::-1]:
    while j < 2 * M + 1 and xsum[i] + ysum[j] <= D:
        j += 1
    ans += j
print(ans)
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

# F - Maximum Composition

# Question

给定 NNN 条线性函数 f1,f2,…,fNf_1, f_2, \ldots, f_Nf1​,f2​,…,fN​,其中 fi(x)=Aix+Bif_i(x) = A_i x + B_ifi​(x)=Ai​x+Bi​。

对于一个由 KKK 个 不同的 整数 p=(p1,p2,…,pK)p = (p_1, p_2, \ldots, p_K)p=(p1​,p2​,…,pK​) 组成的序列,计算 fp1(fp2(…fpK(1)…))f_{p_1}(f_{p_2}(\ldots f_{p_K}(1) \ldots ))fp1​​(fp2​​(…fpK​​(1)…)) 的最大可能值,其中 pip_ipi​ 的取值范围为 111 到 NNN。

# Solution

先考虑 fi(fj(x))>fj(fi(x))f_i(f_j(x))>f_j(f_i(x))fi​(fj​(x))>fj​(fi​(x)) 的等价条件

fi(fj(x))>fj(fi(x))⇔Ai(Ajx+Bj)+Bi>Aj(Aix+Bi)+Bj⇔AiAjx+AiBj+Bi>AiAjx+AjBi+Bj⇔AiBj−Bj>AjBi−Bi⇔(Ai−1)Bj>(Aj−1)Bi⇔(Ai−1)Bi>(Aj−1)Bj \begin{aligned} & f_i(f_j(x))>f_j(f_i(x))\\ \Leftrightarrow \ & A_i(A_j x+B_j)+B_i>A_j(A_ix+B_i)+B_j\\ \Leftrightarrow \ & A_iA_jx+A_iB_j+B_i>A_iA_jx+A_jB_i+B_j\\ \Leftrightarrow \ & A_iB_j-B_j>A_jB_i-B_i\\ \Leftrightarrow \ & (A_i-1)B_j>(A_j-1)B_i\\ \Leftrightarrow \ & \frac{(A_i-1)}{B_i}>\frac{(A_j-1)}{B_j} \end{aligned} ⇔ ⇔ ⇔ ⇔ ⇔ ​fi​(fj​(x))>fj​(fi​(x))Ai​(Aj​x+Bj​)+Bi​>Aj​(Ai​x+Bi​)+Bj​Ai​Aj​x+Ai​Bj​+Bi​>Ai​Aj​x+Aj​Bi​+Bj​Ai​Bj​−Bj​>Aj​Bi​−Bi​(Ai​−1)Bj​>(Aj​−1)Bi​Bi​(Ai​−1)​>Bj​(Aj​−1)​​

所以,我们按照 (Ai−1)Bi>(Aj−1)Bj\frac{(A_i-1)}{B_i}>\frac{(A_j-1)}{B_j}Bi​(Ai​−1)​>Bj​(Aj​−1)​ 的标准,把 (A,B)(A,B)(A,B) 排序

现在我们排完序后有 NNN 个 (A,B)(A,B)(A,B) 我们需要从中选 KKK 个,这个就是一个很朴素的 DP 问题了

定义 f[i][j]f[i][j]f[i][j] 对于前 iii,已经选了 jjj 个的最优解,那么转移方程就是

f[i][j]=max⁡f[i−1][j],f[i−1][j−1]×Aj+Bj f[i][j]=\max f[i-1][j],f[i-1][j-1] \times A_j+B_j f[i][j]=maxf[i−1][j],f[i−1][j−1]×Aj​+Bj​

答案就是 f[N][K]f[N][K]f[N][K]

# Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int main() {
    int n, k; cin >> n >> k;
    vector<int> a(n), b(n);
    for (int i = 0; i < n; i++) cin >> a[i] >> b[i];
    vector<int> ord(n);
    for (int i = 0; i < n; i++) ord[i] = i;
    sort(ord.begin(), ord.end(), [&](int i, int j) {
        return b[i] * (a[j] - 1) > b[j] * (a[i] - 1);
    });
    vector<ll> dp(k + 1, -INF);
    dp[0] = 1;
    for (auto i : ord) {
        auto ndp = dp;
        for (int j = 0; j < k; j++) {
            if (dp[j] != -INF) {
                ndp[j + 1] = max(ndp[j + 1], dp[j] * a[i] + b[i]);
            }
        }
        dp = ndp;
    }
    cout << dp[k] << endl;
    return 0;
}
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
上次更新: 2025/04/08, 18:03:31
AtCoder Beginner Contest 359 A-G 题解
AtCoder Beginner Contest 369 A-F 题解

← AtCoder Beginner Contest 359 A-G 题解 AtCoder Beginner Contest 369 A-F 题解→

最近更新
01
Java基础语法
05-26
02
开发环境配置
05-26
03
pink 老师 JavaScript 学习笔记
05-26
更多文章>
Theme by Vdoing | Copyright © 2024-2025 Martian148 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式