Codeforces Round #544 (Div. 3)簡單題解

復健,時間有限題解比較簡陋node


A. Middle of the Contest

將小時轉成分鐘,獲得起止時間在一天中的分鐘數,取平均值便可,複雜度O(1)。平均值轉換會時間的時候注意前導0。ios

void solve(int x) {
    x /= 2;
    printf("%02d:%02d\n", x / 60, x % 60);
}
int main() {
    // freopen("in.txt", "r", stdin);
    // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)cpp;
    int h1, h2, m1, m2;
    char c;
    cin >> h1 >> c >> m1;
    cin >> h2 >> c >> m2;
    solve(h1 * 60 + m1 + h2 * 60 + m2);
}

B. Preparation for International Women’s Day

要加起來能被k整除, 只須要看模k的餘數便可。餘數爲i的與餘數爲k-i的互補能夠被k整除,經過計數看有多少對能互補。須要注意的是,爲餘數爲0k/2(k爲偶數)時,只能同餘數的互補,此時計數是偶數個時都能配對,奇數個時能配對的數量是計數 - 1。複雜度O(n + k)c++

int main() {
    // freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, k, x, cnt = 0;
    cin >> n >> k;
    int d[k] = {0};
    for (int i = 0; i < n; ++i) cin >> x, d[x % k]++;
    for (int i = 0; i < (k + 1) / 2; ++i) {
        if (i == 0)
            cnt += d[i] / 2;
        else {
            cnt += min(d[i], d[k - i]);
        }
    }
    if (k % 2 == 0) cnt += d[k / 2] / 2;
    cout << cnt * 2;
}

C. Balanced Team

單調隊列,從小到大添加元素,保證隊首和隊尾差不超過5,超過了則出隊,不然用當前隊列大小更新最優解。若是元素x < yx必定比y先入隊,並且能與x共存的最小值sx和能與y共存的最小值sysx <= sy。使用單調隊列,每次入隊後進行出隊操做,出隊完成後隊首就是能與入隊元素共存的最小值,隊列內的元素就是以入隊元素爲最大值時全部能存在的元素。複雜度O(n)數組

int main() {
    // freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    ll a[n + 1];
    for (int i = 1; i <= n; ++i) cin >> a[i];
    sort(a + 1, a + 1 + n);
    int cnt = 0, l = 1, r = 2;
    while (l <= r && r <= n) {
        if (a[r] - a[l] > 5) cnt = max(cnt, r - l), l++;
        r++;
    }
    cnt = max(cnt, r - l);
    cout << cnt;
}

D. Zero Quantity Maximization

d * a[i] + b[i] = 0可得d = - b[i] / a[i],統計每種d取值的個數,取最大便可。對於a[i]0的狀況須要特殊討論,若是b[i]也爲0則此時d能夠取任意值;不然,d的取值爲0。另外,爲了不浮點偏差,不能直接統計d,而是要統計<a, b>這個配對;同時,爲了歸一化,須要將ab同時除以他們的最大公約數,並保證a是正數。複雜度O(nlog(n)),log是由於用了map來計數。spa

// Author : RioTian
// Time : 20/11/10
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int main() {
    // freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    ll a[n + 1], b[n + 1];
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> b[i];
    }
    int zeroBCnt = 0, zeroBothCnt = 0;
    map<pair<int, int>, int> hash;
    for (int i = 0; i < n; ++i) {
        if (a[i] == 0) {
            if (b[i] == 0) ++zeroBothCnt;
            continue;
        }
        if (b[i] == 0) {
            ++zeroBCnt;
        }
        int divisor = gcd(abs(a[i]), abs(b[i]));
        a[i] /= divisor;
        b[i] /= divisor;
        if (a[i] < 0) {
            a[i] = -a[i];
            b[i] = -b[i];
        }
        if (hash[make_pair(a[i], b[i])])
            ++hash[make_pair(a[i], b[i])];
        else
            hash[make_pair(a[i], b[i])] = 1;
    }
    int ans = zeroBCnt;
    for (auto item : hash) {
        if (item.second > ans) ans = item.second;
    }
    cout << ans + zeroBothCnt << endl;
    return 0;
}

E. K Balanced Teams

與C題思路相似,先獲得取每一個元素爲最大值,能共存的元素有哪些(排過序的數組保留首位指針便可),好比位置爲i的元素最小可共存元素的位置是maxStart[i],這樣數組裏面maxStart[i]i都是可共存元素。問題就轉成如何在裏面選k個,讓元素儘可能多,這樣dp便可。dp[i][j]表示前i個元素選j隊的最優值,則若是選maxStart[i]i,最優值爲dp[maxStart[i] - 1], j - 1] + i - maxStart[i] + 1;若是不選,最優值爲dp[i - 1][j];二者取最優獲得狀態轉移方程。另外因爲j只會從j - 1轉移,所以能夠用滾動數組節約內存。複雜度O(nk)指針

// Author : RioTian
// Time : 20/11/10
#include <bits/stdc++.h>
using namespace std;
const int N = 5e3 + 10;
int a[N], maxStart[N], dp[N][2];
int n, k;
int main() {
    cin >> n >> k;
    for (int i = 0; i < n; ++i) cin >> a[i];
    sort(a, a + n);
    int l = 0, r = 0;
    while (r < n) {
        if (a[r] - a[l] <= 5) {
            maxStart[r] = l, ++r;
            continue;
        }
        ++l;
    }
    for (int i = 1; i <= k; ++i) {
        for (int j = 0; j < n; ++j) {
            if (maxStart[j]) {
                dp[j][i % 2] =
                    max(dp[j - 1][i % 2],
                        dp[maxStart[j] - 1][(i - 1) % 2] + j - maxStart[j] + 1);
                continue;
            }
            dp[j][i % 2] = max(dp[j - 1][i % 2], j - maxStart[j] + 1);
        }
    }
    cout << dp[n - 1][k % 2] << endl;
    return 0;
}

F1. Spanning Tree with Maximum Degree

直接找到度最大的節點bfs便可,複雜度O(n + m)code

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

vector<int> node[200010];
bool visited[200010];

void bfs(int start) {
    queue<int> qu;
    qu.push(start);
    visited[start] = true;
    while (qu.size()) {
        int cur = qu.front();
        qu.pop();
        for (auto next : node[cur]) {
            if (visited[next]) continue;
            visited[next] = true;
            qu.push(next);
            cout << cur + 1 << ' ' << next + 1 << endl;
        }
    }
}

int main() {
    int n, m, x, y, tmp, maxCnt = 0, maxNode = -1;
    cin >> n >> m;
    for (int i = 0; i < m; ++i) {
        cin >> x >> y;
        --x;
        --y;
        node[x].push_back(y);
        node[y].push_back(x);
        tmp = node[x].size() > node[y].size() ? x : y;
        if (node[tmp].size() > maxCnt) {
            maxCnt = node[tmp].size();
            maxNode = tmp;
        }
    }
    bfs(maxNode);
    return 0;
}

F2. Spanning Tree with One Fixed Degree

若是從1的一個分支出發能從另外一個分支回到1,則這些分支劃分爲同一組,dfs便可獲得這些分組。若是一組裏面全部分支都被去掉了,則這組裏面的節點就沒法出如今樹裏面,所以至少要保留一個。dfs獲得有多少這樣的組,每組裏面取一個分支,剩下還能夠取則任意取。這些分支做爲bfs的第一步,繼續搜下去,按搜索順序輸出便可。非法的狀況有:dfs時存在節點沒有走到;須要的度數比組數少(此時至少有一組全部分支都被去掉);須要的度數比1連接的分支多。複雜度O(n + m)隊列

#include <cstring>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;
bool visited[200010];
vector<int> node[200010];
vector<int> group[200010];
queue<int> qu;
int n, m, d, g;

void dfs(int cur, int parent) {
    visited[cur] = true;
    for (auto next : node[cur]) {
        if (visited[next]) {
            if (parent == -1) group[g - 1].push_back(next);
            continue;
        }
        if (parent == -1) {
            group[g++].push_back(next);
        }
        dfs(next, cur);
    }
}

void bfs() {
    while (qu.size()) {
        int cur = qu.front();
        qu.pop();
        for (auto next : node[cur]) {
            if (!visited[next]) {
                visited[next] = true;
                cout << cur + 1 << ' ' << next + 1 << endl;
                qu.push(next);
            }
        }
    }
}

int main() {
    int x, y;
    cin >> n >> m >> d;
    for (int i = 0; i < m; ++i) {
        cin >> x >> y;
        --x;
        --y;
        node[x].push_back(y);
        node[y].push_back(x);
    }
    memset(visited, 0, sizeof(visited));
    dfs(0, -1);
    for (int i = 0; i < n; ++i) {
        if (!visited[i]) {
            cout << "NO" << endl;
            return 0;
        }
    }
    if (g > d || node[0].size() < d) {
        cout << "NO" << endl;
        return 0;
    }
    cout << "YES" << endl;
    memset(visited, 0, sizeof(visited));
    visited[0] = true;
    d -= g;
    for (int i = 0; i < g; ++i) {
        cout << '1' << ' ' << group[i][0] + 1 << endl;
        visited[group[i][0]] = true;
        qu.push(group[i][0]);
        for (int j = 1; d && j < group[i].size(); ++j) {
            cout << '1' << ' ' << group[i][j] + 1 << endl;
            visited[group[i][j]] = true;
            qu.push(group[i][j]);
            --d;
        }
    }
    bfs();
    return 0;
}
相關文章
相關標籤/搜索