Featured image of post Codeforces Round #615 (Div. 3)

Codeforces Round #615 (Div. 3)

Codeforces Round

Codeforces Round #615 (Div. 3)

第一次 CF 賽中破台,排名 +178,總算 1700 了。 pD 稍微想了一下子,pE 實作上卡了很久,有些邊界問題沒考慮清楚。pF 想了一下子才發現很好寫,但忘了考慮一直鏈的情況,所以 WA 了一次。

A. Collecting Coins

 1#include<bits/stdc++.h>
 2using namespace std;
 3typedef long long LL;
 4int main() {
 5    ios::sync_with_stdio(0), cin.tie(0);
 6    int t; cin >> t;
 7    while (t--) {
 8        LL a, b, c, n;
 9        cin >> a >> b >> c >> n;
10        LL sum = n + a + b + c;
11        if (sum % 3) {
12            cout << "NO\n";
13            continue;
14        }
15        sum /= 3;
16        if (sum < a || sum < b || sum < c) {
17            cout << "NO\n";
18            continue;
19        }
20        cout << "YES\n";
21    }   
22    return 0;
23}

B. Collecting Coins

 1#include<bits/stdc++.h>
 2using namespace std;
 3typedef pair<int, int> pii;
 4#define x first
 5#define y second
 6int main() {
 7    ios::sync_with_stdio(0), cin.tie(0);
 8    int t; cin >> t;
 9    while (t--) {
10        int n; cin >> n;
11        vector<pii> p(n);
12        for (int i = 0; i < n; i++) cin >> p[i].x >> p[i].y;
13        sort(p.begin(),p.end());
14        bool success = true;
15        for (int i = 1; i < n; i++)
16            if(p[i].x < p[i-1].x || p[i].y < p[i-1].y)
17                success = false;
18        if(!success) {
19            cout << "NO\n";
20            continue;
21        }
22        cout << "YES\n";
23        int xx = 0, yy = 0;
24        for(int i = 0; i < n; i++) {
25            while (xx != p[i].x) cout << "R", xx++;
26            while (yy != p[i].y) cout << "U", yy++;
27        }
28        cout << "\n";
29    }
30    return 0;
31}

C. Product of Three Numbers

 1#include<bits/stdc++.h>
 2using namespace std;
 3int main() {
 4    ios::sync_with_stdio(0), cin.tie(0);
 5    int t; cin >> t;
 6    while (t--) {
 7        int n; cin >> n;
 8        vector<int> ans;
 9        for (int i = 2; i * i <= n && ans.size() < 2; i++) {
10            if (n % i) continue;
11            ans.push_back(i);
12            n /= i;
13        }
14        if (ans.size() != 2 || n <= ans.back()) {
15            cout << "NO\n";
16            continue;
17        }
18        cout << "YES\n";
19        ans.push_back(n);
20        for (int i = 0; i < 3; i++)
21            cout << ans[i] << " \n"[i==2];
22    }
23    return 0;
24}

D. MEX maximizing

每次新增一個數字到序列裡,可對序列每個數字任意加減x的整數倍,問操作完後,序列中所缺的最小正整數最大是多少?

一開始可以確定答案不可能超過當前 query 的次數,且答案會單調遞增。可以知道 y[i] 可以加減 x 的整數倍,故可以直接 y[i] 紀錄 mod x 出現幾次,然後將答案往後爬。複雜度 O(q)。

 1#include<bits/stdc++.h>
 2using namespace std;
 3#define MAX 800005
 4int main() {
 5    ios::sync_with_stdio(0), cin.tie(0);
 6    int q, x; cin >> q >> x;
 7    int ans = 0;
 8    int cnt[MAX] = {};
 9    for (int i = 0; i < q; i++) {
10        int a; cin >> a;
11        cnt[a % x]++;
12        while (cnt[ans % x]){
13            cnt[ans % x]--;
14            ans++;
15        }
16        cout << ans << "\n";
17    }
18    return 0;
19}

E. Obtain a Permutation

只需要將每個 column 單獨計算,再將所有結果相加即可。

單一個 column,對每一格去算到達正確位置需要幾次操作,用個陣列去計算,轉 k 次能讓多少個格子到達正確位置。總複雜度 O(mn)。

 1#include<bits/stdc++.h>
 2using namespace std;
 3#define MAX 200005
 4int cnt[MAX] = {};
 5int main() {
 6    ios::sync_with_stdio(0), cin.tie(0);
 7    int n, m; cin >> n >> m;
 8    vector<vector<int>> a(n, vector<int>(m));
 9    for (int i = 0; i < n; i++)
10        for (int j = 0; j < m; j++)
11            cin >> a[i][j];
12    int sum = 0;
13    for (int j = 0; j < m; j++) {
14        for (int i = 0; i < n; i++) {
15            if (a[i][j] <= n * m && (j+1) % m == a[i][j] % m) {
16                int ii = (a[i][j] - 1) / m;
17                cnt[(i + n - ii) % n]++;
18            }
19        }
20        int ans = MAX;
21        for (int i = 0; i < n; i++) {
22            ans = min(ans, n - cnt[i] + i);
23            cnt[i] = 0;
24        }
25        sum += ans;
26    }
27    cout << sum << "\n";
28    return 0;
29}

F. Three Paths on a Tree

找出相異三點,使得兩兩之間的路徑聯集起來邊數最多。

若樹為一直鏈(竹子),則答案為兩端點,和中間任一點。其餘的情況,可以確定答案必有一點落在直徑上,且三點皆為葉子。故先做兩次 BFS 找出直徑,再做樹 DP 得到答案。複雜度 O(n)。

 1#include<bits/stdc++.h>
 2using namespace std;
 3#define maxn 200005
 4vector<int> v[maxn];
 5bool visit[maxn] = {1,1};
 6typedef pair<int, int> pii;
 7int ans = 0;
 8int out[3];
 9pii dfs(int u, int dep, int scr) {
10    visit[u] = true;
11    int mx1 = 0, mx2 = 0, a1 = u, a2 = u;
12    for (int uu : v[u]) {
13        if(visit[uu]) continue;
14        pii d = dfs(uu, dep + 1, scr);
15        if (d.first >= mx1)
16            mx2 = mx1, a2 = a1, mx1 = d.first, a1 = d.second;
17        else if (d.first > mx2)
18            mx2 = d.first, a2 = d.second;
19    }
20    if (mx1 + mx2 + dep >= ans) {
21        ans = mx1 + mx2 + dep;
22        out[0] = scr, out[1] = a1, out[2] = a2;
23    }
24    return pii(mx1 + 1, a1);
25}
26int main() {
27    ios::sync_with_stdio(0), cin.tie(0);
28    int n; cin >> n;
29    for (int i = 1; i < n; i++) {
30        int a, b; cin >> a >> b;
31        v[a].push_back(b), v[b].push_back(a);
32    }
33    queue<int> q;
34    int a = 1;
35    q.push(1);
36    while (!q.empty()) {
37        int u = q.front(); q.pop();
38        a = u;
39        for(int uu : v[u])
40            if (!visit[uu])
41                visit[uu] = true, q.push(uu);
42    }
43    int b = a;
44    memset(visit, 0, sizeof(visit));
45    q.push(a);
46    while(!q.empty()) {
47        int u = q.front(); q.pop();
48        b = u;
49        for (int uu : v[u])
50            if (!visit[uu])
51                visit[uu] = true, q.push(uu);
52    }
53    memset(visit, 0, sizeof(visit));
54    dfs(a, 0, a);
55    memset(visit, 0, sizeof(visit));
56    dfs(b, 0, b);
57    cout << ans << "\n";
58    if (out[1] == out[2] || out[0] == out[2]) {
59        for (int i = 1; i <= n; i++)
60            if (i != out[0] && i != out[1]){
61                out[2] = i;
62                break;
63            }
64    }
65    for (int i = 0; i < 3; i++)
66        cout << out[i] << " \n"[i == 2];
67    return 0;
68}
Built with Hugo
Theme Stack designed by Jimmy