首页 > 其他分享 >Codeforces Round 975 (Div. 2)

Codeforces Round 975 (Div. 2)

时间:2024-09-30 15:02:26浏览次数:9  
标签:lf sz 975 int Codeforces rf maxn && Div

C. Cards Partition (C)

对于每个确定的size,有便捷的方法判断该值是否合法:组数最小为 \(a_{max}\),若 \(k\) 张牌可以填出 \(a_{max}\) 组牌堆则合法;将余下的牌当成新的一组,若 \(k\) 张牌可以凑出一整组则合法;其余情况不合法。由于check过程为 \(O(1)\),可从大到小暴力枚举size,时间复杂度 \(O(n)\).

void solve() {
    scanf("%d%lld", &n, &k);
    sum = maxn = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
        sum += a[i];
        maxn = max(maxn, a[i]);
    }
    for(int i = n; i; i--) {
        if(sum + k < i * maxn) continue;
        ll ss = i * maxn;
        if(ss >= sum) {
            printf("%d\n", i);
            return;
        }
        ll lst = sum % i;
        if(lst == 0 || k + lst >= i) {
            printf("%d\n", i);
            return;
        }
    }
}

D. Speedbreaker (D)

(搞了个假做法没写出来,6)

当 \(t = i\) 时,找到 \(a\leq i\) 的最左侧与最右侧城市,其间的所有城市都必须在 \(t\) 时间内到达。具体地,设两侧城市为 \(l,r\),则到 \(l, r\) 位置距离之和 \(\leq i\) 的所有城市可能成为起点,差分处理即可。最后求缀和检查每个位置被多少合法区间所覆盖,被全部区间覆盖的城市即合法起点。

void solve() {
    int n;
    scanf("%d", &n);
    fill(s + 1, s + n + 1, 0);
    fill(l + 1, l + n + 1, 0);
    for(int i = 1; i <= n; i++) {
        int x;
        scanf("%d", &x);
        if(!l[x]) l[x] = i;
        r[x] = i;
    }
    int L = 1e9, R = 0;
    for(int i = 1; i <= n; i++) {
        if(l[i]) {
            L = min(L, l[i]), R = max(R, r[i]);
            l[i] = L, r[i] = R;
        }
    }
    int cnt = 0, ans = 0;
    for(int i = 1; i <= n; i++) {
        if(l[i]) {
            int L = max(1, r[i] - i + 1);
            int R = min(n, l[i] + i - 1);
            if(R - L + 1 < i) {
                printf("0\n");
                return;
            }
            s[L]++, s[R + 1]--, cnt++;
        }
    }
    for(int i = 1; i <= n; i++) {
        s[i] += s[i - 1];
        if(s[i] == cnt) ans++;
    }
    printf("%d\n", ans);
}

E. Tree Pruning (E)

一个点被砍掉有两种可能:最终树深度小于其深度,或者最终树深度大于其最深叶子节点的深度。与D同理,差分+前缀和求解,取前缀和最小值。

int dfs(int f, int i) {
    tar[i] = dep[i] = dep[f] + 1;
    for(int t : v[i]) {
        if(t == f) continue;
        tar[i] = max(tar[i], dfs(i, t));
    }
    return tar[i];
}
void solve() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        v[i].clear();
        sum[i] = 0;
    }
    for(int i = 1; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(0, 1);
    for(int i = 1; i <= n; i++) {
        sum[1]++;
        sum[dep[i]]--;
        sum[tar[i] + 1]++;
    }
    int ans = 1e9;
    for(int i = 1; i <= n; i++) {
        sum[i] += sum[i - 1];
        ans = min(ans, sum[i]);
    }
    printf("%d\n", ans);
}

F. Max Plus Min Plus Size (F)

在最小值确定的情况下,对于一段连续序列,选择包含最大值的所有奇数或偶数位置是最优的,即红色数字数量为 \(s / 2\)(s为奇数且最大值在偶数位置)或 \((s + 1) / 2\). 从大至小枚举最小值,用并查集维护所有连续序列,每次将当前最小值加入并查集中,动态维护当前的数字数量与最大值的奇偶位置即可。

const int N = 2e5 + 10;
int a[N], f[N], sz[N];
int find(int i) {
    if(f[i] == i) return i;
    return f[i] = find(f[i]);
}
map <int, vector <int> > mp;
void solve() {
    int n;
    scanf("%d", &n);
    mp.clear();
    int maxn = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        mp[-a[i]].push_back(i);
        f[i] = i, sz[i] = 1;
        maxn = max(maxn, a[i]);
    }
    int ans = 0, sum = 0, flag = 0;
    for(auto x : mp) {
        int minn = -x.first;
        for(int t : x.second) {
            if(t > 1 && t < n && a[t - 1] >= a[t] && a[t + 1] > a[t]) {
                int lf = find(t - 1), rf = find(t + 1);
                int l = t - sz[lf];
                if(a[lf] == maxn && ((sz[lf] & 1) == 0 || ((lf - l + 1) & 1))) flag--;
                if(a[rf] == maxn && ((sz[rf] & 1) == 0 || ((rf - t) & 1))) flag--;
                sum -= (sz[lf] + 1) / 2;
                sum -= (sz[rf] + 1) / 2;
                if(a[lf] > a[rf]) swap(lf, rf);
                sz[rf] += sz[lf] + 1;
                sum += (sz[rf] + 1) / 2;
                f[lf] = f[t] = rf;
                if(a[lf] == maxn && a[rf] == maxn && ((lf & 1) != (rf & 1))) flag = 1e9;
                if(a[rf] == maxn && ((sz[rf] & 1) == 0 || ((rf - l + 1) & 1))) flag++;
            } else if(t > 1 && a[t - 1] >= a[t]) {
                int lf = find(t - 1);
                int l = t - sz[lf];
                if(a[lf] == maxn && ((sz[lf] & 1) == 0 || ((lf - l + 1) & 1))) flag--;
                sum -= (sz[lf] + 1) / 2;
                sz[lf]++;
                sum += (sz[lf] + 1) / 2;
                f[t] = lf;
                if(a[t] == maxn && a[lf] == maxn && ((lf & 1) != (t & 1))) flag = 1e9;
                if(a[lf] == maxn && ((sz[lf] & 1) == 0 || ((lf - l + 1) & 1))) flag++;
            } else if(t < n && a[t + 1] > a[t]) {
                int rf = find(t + 1);
                int l = t;
                if(a[rf] == maxn && ((sz[rf] & 1) == 0 || ((rf - t) & 1))) flag--;
                sum -= (sz[rf] + 1) / 2;
                sz[rf]++;
                sum += (sz[rf] + 1) / 2;
                f[t] = rf;
                if(a[t] == maxn && a[rf] == maxn && ((rf & 1) != (t & 1))) flag = 1e9;
                if(a[rf] == maxn && ((sz[rf] & 1) == 0 || ((rf - l + 1) & 1))) flag++;
            } else {
                sum++;
                if(a[t] == maxn) flag++;
            }
        }
        int ss = sum + maxn + minn;
        if(!flag) ss--;
        ans = max(ans, ss);
    }
    printf("%d\n", ans);
}

标签:lf,sz,975,int,Codeforces,rf,maxn,&&,Div
From: https://www.cnblogs.com/meowqwq/p/18441851

相关文章

  • Codeforces Round 976 (Div. 2)
    传送门A.输出\(n\)在\(k\)进制下各数位之和B.一个位置被反转当且仅当有奇数个因子,有奇数个因子的数一定是完全平方数。二分\(n\)即可C.枚举二进制下每一位,发现\(b,c,d\)再这一位最多有八种可能,对于每一种情况都能得到在这一位\(a\)的值,分类讨论就行了。D.E.\(......
  • Codeforces Round 976 (Div. 2)
    B:很容易发现只有因数个数为偶数的灯泡是亮的。所以只有完全平方数的因数是奇数个。实现上可以二分。但是sqrt是double的必须开sqrtl才是longdouble的,才能满足这题longlong的数据范围。人给我卡傻了。哈哈。#include<bits/stdc++.h>usingnamespacestd;#defineintunsign......
  • Codeforces Round 975 (Div. 2) CE
    来源:CodeforcesRound975(Div.2)C.CardsPartition题意本身有\(a_i\)张\(i\)牌,现在将牌分成若干份,每一份牌数相等,且每一份都由不同的牌组成同时有\(k\)次补充任意牌的机会,求最多分成一份几张牌思路假定分成\(m\)份,每份\(p\)张牌,那么所有牌加补充的牌等于\(m*p......
  • Codeforces Round 975 (Div. 2) A~F 题解(Div.1 A~D)
    CodeforcesRound975(Div.2)A~F题解(Div.1A~D)也是补完整场了。A.MaxPlusSize枚举最大值的位置,使长度最长,更新答案。B.AllPairsSegments每个线段内部的点的答案都是一样的,在处理一下线段两边边界的点。被包含次数就是左边\(\times\)右边。用\(map\)记录答案......
  • Codeforces Round 975 (Div. 2)
    目录写在前面A签到B排序,模拟C数学,贪心D模拟,思维E树,贪心,暴力or长链剖分F贪心,枚举写在最后写在前面比赛地址:https://codeforces.com/contest/2019。唉唉不敢打div1只敢开小号打div2太菜了。A签到显然最优方案只有两种——取所有奇数位置或所有偶数位置。///*By......
  • Codeforces Round 975 (Div. 2) A-E
    人生中第一次正常\(div2\)爆写5题。cf给我正反馈最大的一次A直接找到最大的数字的位置,然后判断一下这个数字的位置下标的奇偶性就好了。然后如果有多个最大的就取奇数位置的。这样可以算出来一定是最优解#include<bits/stdc++.h>#definelllonglongusingnamespacestd;inl......
  • Codeforces Round 975 Div.2 C题 解析
    C题题目链接:Problem-C-Codeforces题目描述思路......
  • Codeforces Round 975 (Div. 2) 题解:D、E
    第一次进前50,上分最爽的一次D.Speedbreaker对\(a\)按照时间升序排序,不难发现,对于升序排序后的数组,当我们搜到时间\(t\)时,记录已经搜过的时间对应原城市编号最小值为\(l\),最大值为\(r\),则我们一定要在\(a_t\)时间之前走过所有\([l,r]\)之间的城市。则若\(r-l+1>a_t\)则无解,因......
  • Codeforces Round 944 (Div. 4) A~G题解
    A\(min\)函数和\(max\)函数的使用,按照格式输出即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpair<int,int>PII;voidsolve(){intx,y;cin>>x>>y;cout<<min(x,y)<<'......
  • Codeforces Round 973题解(E)
    E.PrefixGCD假设我们从一个空集合\(b\)开始,不断从\(a\)数组中选择一个元素添加到\(b\)集合的尾部,当把\(a\)数组的元素全部添加到\(b\)中后,得到的\(b\)即为所求的rearrange后的\(a\)。结论1:每次选择使得其和当前\(b\)中所有元素的最大公约数最小的那个\(a_i\)加入到\(b\)的末......