Codeforces Round 936 (Div. 2) (A~C)

前言

写的时候B题题意读错了,C题二分边界调歪了又没注意到,心态大崩,美美掉分......
D题之后补完再更新吧。

A. Median of an Array 贪心

发现原数组顺序没有用,显然先进行一个排序,找中位数的点,往后遍历找与中位数相同的有多少个,全部加一就可以实现最后落到中位数位置的数一定变大。

    void solve(int ce){
        cin >> n;
        for(int i = 1; i <= n; i++){
            cin >> a[i];
        }
        int cnt = 1;
        sort(a + 1, a + n + 1);
        for(int i = (n + 1)/2 + 1;i <= n; i++){
            if(a[(n + 1)/2] == a[i]){
                cnt++;
            }
            else break;
        }
        cout << cnt << endl;
    }

B. Maximum Sum 贪心

题意是每次操作选取一个任意连续子数组和,然后把和插到原数组任意位置,然后求K次操作后最大数组和。
一开始被取模迷惑了以为是求数组和取模后最大,绞尽脑汁了半天
只用求一个最大子数组和,然后每次把这个和插入到原来子数组里,如果这个子数组和比原来小,那就不操作。

    void solve(int ce){
        cin >> n >> k;
        int ans = 0,sum = 0;
        for(int i = 1; i <= n; i++){
            cin >> a[i];
            ans += a[i];
        }
        int res=-INF;
        dp[0]=0;
        for(int i=1;i <= n; i++){
            dp[i]=max(dp[i - 1] + a[i],a[i]);
            res = max(dp[i],res);
        }
        sum = res;
        if(sum <= 0){
            cout << ((ans % mod) + mod) % mod << endl;
        }
        else {
            ans -= sum;
            ans = ((ans % mod) + mod) % mod;
            for(int i = 1; i <= k; i++){
                sum = sum * 2 % mod;
            }
            cout << (ans + sum + mod) % mod << endl;
        }
    }

C. Tree Cutting 二分,贪心

题意是把一棵树分成\(k\)个连通块,使得最小那个最大。
二分答案,然后用\(dfs\)进行\(check\),如果这个子树大小 \(\geqslant mid\) 那么将当前子树断开,即把当前结点子树大小改为\(0\),连通块个数加一。比较连通块个数和\(k\)

    int dp[N];
    int res = 0;
    vector<int> g[N];
    void dfs(int u, int fa, int x){
        dp[u] = 1;
        for(auto v : g[u])if(v != fa){
            dfs(v, u, x);
            dp[u] += dp[v];
        }
        if(dp[u] >= x){
            res++;
            dp[u] = 0;
        }
    }
    void solve(int ce){
        cin >> n >> k;
        for(int i = 1, u, v; i < n; i++){
            cin >> u >> v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
        int l = 1, r = n;
        while(l < r){
            res = 0;
            int mid = l + r >> 1;
            dfs(1, 0, mid);
            if(res > k){
                l = mid + 1;
            }
            else r = mid - 1;
        }
        int ans = 1;
        for(int i = max(1ll, l - 1); i <= min(n, l); i++){
            res = 0;
            dfs(1, 0, i);
            if(res > k){
                ans = i;
            }
        }//小规模暴力了一下,省的调边界
        cout << ans << endl;
        for(int i = 1; i <= n; i ++){
            g[i].clear();
        }
    }
posted @ 2024-03-23 11:35  SHOJIG  阅读(180)  评论(0)    收藏  举报