Codeforces Round 890 (Div.2)

发布时间 2023-08-07 02:06:31作者: wuyoudexian

赛时没想到c是二分答案

C. To Become Max

题意

给定一个长度为\(n\)的数组\(a\),可对\(a_i\)加1当\(a_i\le a_{i+1}\),最多可进行\(k\)次这样的操作,求最多\(k\)次操作后数组\(a\)中的最大值。

思路

首先找出原数组中最大的值,然后枚举1到n-1,对每个点二分答案,维护最大值。

代码

void solve() {
    int n, k;
    cin >> n >> k;
 
    vector<int> a(n);
    int ans = 0;
    for(int i = 0; i < n; i++) {
        cin >> a[i];
        ans = max(ans, a[i]);
    }
 
    for(int i = 0; i < n - 1; i++) {
        int lo = a[i], hi = 2e8;
        while(lo < hi) {
            int mid = lo + hi + 1 >> 1;
            ll cost = 0;
            bool ok = false;
 
            for(int j = i, x = 0; j < n - 1; j++, x++) {
                if(a[j] >= mid - x) break;
                if(j == n - 2 && a[j + 1] + 1 < mid - x) {
                    ok = true;
                }
                cost += mid - x - a[j];
            }
 
            if(ok || cost > k) {
                hi = mid - 1;
            } else {
                lo = mid;
            }
        }
 
        ans = max(ans, lo);
    }
 
    cout << ans << "\n";
}

E1. PermuTree (easy version)

题意

给定一棵树,给每个节点赋权值\(p_1,p_2\cdots p_n\),且\(p_1,p_2\cdots p_n\)是一个排列。求一种赋权值的方案,最大化符合条件的二元组\((u,v)\)的数量。二元组\((u,v)\)符合条件当且仅当\(p_u<p_{lca(u,v)}<p_v\)

思路

首先dfs一遍求的每个节点的子节点数量。要使得二元组数量最多,我们把每个节点的子树分为两块,让两块子树的节点数相乘最大。要使得两块子树的节点数相乘最大,就尽量让两部分节点数尽量接近,这个可以用01背包解决,设容量为所有子节点数量的一半。

代码

#include<bits/stdc++.h>

using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;

    vector<vector<int>> adj(n + 1);
    for(int i = 2; i <= n; i++) {
        int p;
        cin >> p;
        adj[p].push_back(i);
    }

    vector<int> siz(n + 1, 1);
    auto getSize = [&](auto self, int u) ->int {
        for(int v : adj[u]) {
            siz[u] += self(self, v);
        }
        return siz[u];
    };
    getSize(getSize, 1);

    int ans = 0;
    for(int x = 1; x <= n; x++) {
        int sum = siz[x] - 1 >> 1;
        vector<int> dp(sum + 1);
        for(int y : adj[x]) {
            for(int k = sum; k >= siz[y]; k--) {
                dp[k] = max(dp[k], dp[k - siz[y]] + siz[y]);
            }
        }
        ans += dp[sum] * (siz[x] - dp[sum] - 1);
    }

    cout << ans << "\n";

    return 0;
}