Codeforces Round 811 (Div. 3) 题解 A~G | JorbanS

A - Everyone Loves to Sleep

void solve() {
    cin >> n >> t.aa >> t.bb;
    for (int i = 0; i < n; i ++) cin >> a[i].aa >> a[i].bb;
    sort(a, a + n);
    a[n] = {a[0].aa + 24, a[0].bb};
    int l = 0, r = n;
    while (l < r) {
        int mid = l + r >> 1;
        if (t.aa < a[mid].aa || t.aa == a[mid].aa && t.bb <= a[mid].bb) r = mid;
        else l = mid + 1;
    }
    int h = a[l].aa - t.aa, w = a[l].bb - t.bb;
    if (w < 0) h --, w += 60;
    cout << h << ' ' << w << endl;
}

B - Remove Prefix

int solve() {
    cin >> n;
    for (int i = 0; i < n; i ++) cin >> a[i];
    set<int> st;
    for (int i = n - 1; i >= 0; i --) {
        if (st.count(a[i])) return i + 1;
        st.insert(a[i]);
    }
    return 0;
}

C - Minimum Varied Number

string solve() {
    cin >> n;
    string ans;
    int t = 9;
    while (n) {
        if (n > t) ans += char('0' + t), n -= t --;
        else ans += char('0' + n), n = 0;
    }
    reverse(ans.begin(), ans.end());
    return ans;
}

D - Color with Occurrences

区间覆盖问题,每次找能与左边已选的区间接轨,并且贪心地选择尽可能往右延申的区间

int n, m;
string t, s[M];

void solve() {
    cin >> t >> m;
    n = t.size();
    for (int i = 0; i < m; i ++) cin >> s[i];
    vector<pii> e[n + 1];
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < m; j ++) {
            if (i + s[j].size() - 1 >= n) continue;
            if (t.substr(i, s[j].size()) == s[j]) e[i].emplace_back(i + s[j].size() - 1, j);
        }
    vector<pii> ans;
    int l = -1, r = -1;
    while (r < n - 1) {
        pii t;
        t.aa = t.bb = -1;
        for (int i = l + 1; i <= r + 1; i ++)
            for (auto j : e[i]) t = max(t, j);
        if (t.aa < 0) {
            cout << -1 << endl;
            return;
        }
        r = t.aa, l = r - s[t.bb].size() + 1;
        ans.emplace_back(t.bb + 1, l + 1);
    }
    cout << ans.size() << endl;
    for (auto [x, y] : ans) cout << x << ' ' << y << endl;
}

E - Add Modulo 10

只存在 0 或 5,5 先 +5,判断是否全一致

其他奇数先 ×2,只剩偶数

偶数分两类,循环节是 20,只能存在一类偶数

int n, m;
int a[N];

string solve() {
    cin >> n;
    for (int i = 0; i < n; i ++) cin >> a[i];
    int cnt0 = 0, cnt5 = 0, cnt = 0, Max = 0;
    for (int i = 0; i < n; i ++) {
        if (a[i] % 10 == 0) cnt0 ++;
        else if (a[i] % 5 == 0) cnt5 ++, a[i] += 5;
        else if (a[i] & 1) a[i] = (a[i] + a[i] % 10) % 20, cnt ++;
        else a[i] %= 20, cnt ++;
        if (a[i] > a[Max]) Max = i;
    }
    if (cnt0 + cnt5 && cnt) return no;
    if (cnt0 + cnt5) {
        for (int i = 1; i < n; i ++)
            if (a[i] != a[i - 1]) return no;
        return yes;
    }
    for (int i = 0; i < n; i ++)
        if (a[i] == 14 || a[i] % 3 == 0) cnt --;
    if (!cnt || cnt == n) return yes;
    return no;
}

F - Build a Tree and That Is It

有两种情况,一种是一个点在另外连个点形成的路径上

另一种是三个点从一个根延申出去

int n, m;
int d12, d23, d31;
int idx;

void f(int u, int v, int w) {
    cout << u << ' ' << (w == 1 ? v : idx) << endl;
    for (int i = 0; i < w - 2; i ++, idx ++) cout << idx << ' ' << idx + 1 << endl;
    if (w != 1) cout << idx ++ << ' ' << v << endl;
}

void solve() {
    cin >> n >> d12 >> d23 >> d31;
    if (d12 + d23 < d31 || d12 + d31 < d23 || d23 + d31 < d12 || (d12 + d23 + d31) & 1) {
        cout << no << endl;
        return;
    }
    if (d12 + d23 == d31 || d12 + d31 == d23 || d23 + d31 == d12) {
        cout << yes << endl;
        idx = 4;
        if (d12 + d23 == d31) f(1, 2, d12), f(2, 3, d23);
        if (d12 + d31 == d23) f(2, 1, d12), f(1, 3, d31);
        if (d23 + d31 == d12) f(2, 3, d23), f(3, 1, d31);
    } else {
        int s = d12 + d23 + d31 >> 1;
        int d1 = s - d23, d2 = s - d31, d3 = s - d12;
        if (d1 <= 0 || d2 <= 0 || d3 <= 0 || d1 + d2 + d3 >= n) {
            cout << no << endl;
            return;
        }
        cout << yes << endl;
        idx = 5;
        f(1, 4, d1), f(2, 4, d2), f(3, 4, d3);
    }
    while (idx <= n) cout << 1 << ' ' << idx ++ << endl;
}

G - Path Prefixes

树上前缀和

int n, m;
ll A[N], B[N];
int ans[N];
int cnt;

struct Node { int v, a, b; };
vector<vector<Node>> e(N);

void dfs(int u = 1, int fa = 0) {
    for (auto [v, a, b] : e[u]) {
        if (v == fa) continue;
        A[v] = A[u] + a;
        B[cnt + 1] = B[cnt] + b;
        cnt ++;
        ans[v] = upper_bound(B + 1, B + cnt + 1, A[v]) - B - 1;
        dfs(v, u);
        cnt --;
    }
}

void solve() {
    cin >> n;
    for (int i = 1; i <= n; i ++) e[i].clear();
    for (int i = 2; i <= n; i ++) {
        int p, a, b; cin >> p >> a >> b;
        e[p].push_back({i, a, b});
    }
    cnt = 0;
    dfs();
    for (int i = 2; i <= n; i ++) cout << ans[i] << ' ';
    cout << endl;
}

你可能感兴趣的:(OI,题解,算法,深度优先,图论)