首页 > 其他分享 >Codeforces Round 945 (Div. 2) A-D

Codeforces Round 945 (Div. 2) A-D

时间:2024-05-18 16:20:16浏览次数:20  
标签:return int 945 Codeforces cin using Div ldots define

A. Chess For Three

模拟

首先可以发现每一次对局三人的得分总和加 \(2\),所以若干次对局后得分总和也一定是 \(2\) 的倍数,然后为了使和棋数量尽可能多,一直让得分最高的两人和棋且得分数各减 \(1\) 直到无法做出和棋为止。

#include <bits/stdc++.h>

using namespace std;

#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()

using i64 = long long;
using i128 = __int128;

const int INF = 0x3f3f3f3f;

void solve() {
    vector<int> p(3);
    cin >> p[0] >> p[1] >> p[2];

    int sum = accumulate(all(p), 0);
    if (sum % 2) {
        cout << -1 << '\n';
    } else {
        int ans = 0;
        sort(all(p));
        while (p[2] != 0 && p[1] != 0) {
            p[1]--, p[2]--;
            ans++;
            sort(all(p));
        }

        cout << ans << '\n';
    }
}

void prework() {
}

int main() {
    cctie;

    prework();

    int T;
    cin >> T;

    while (T--) {
        solve();
    }

    return 0;
}

B. Cat, Fox and the Lonely Array

二分、前缀和

考虑二分 \(k\),判断数组 \(a\) 是否满足 \(k-lonely\),可通过预处理二进制下 \(n\) 个数每一位的前缀和,然后判断时对每两个相邻 \(k\) 子数组判断相等即可,判断相等看每一位的布尔值是否都相同。

证明可二分性:如果数组 \(a\) 为 \(k-lonely\),则有 \((a_i | \ldots | a_{i+k-1}) = (a_{i+1} | \ldots | a_{i+k}) = (a_{j} | \ldots | a_{j+k-1} )= (a_{j+1} | \ldots | a_{j+k})\),而 \((a_i | \ldots | a_{i+k}) = (a_i | \ldots | a_{i+k-1}) | (a_{i+1} | \ldots | a_{i+k}),\ (a_j | \ldots | a_{j+k}) = (a_{j} | \ldots | a_{j+k-1} )|(a_{j+1} | \ldots | a_{j+k})\),则有 \((a_i | \ldots | a_{i+k})=(a_j | \ldots | a_{j+k})\),能推出 \(a\) 为 \(k+1-lonely\)​。

时间复杂度: \(O(20nlogn)\)。

#include <bits/stdc++.h>

using namespace std;

#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()

using i64 = long long;
using i128 = __int128;

const int INF = 0x3f3f3f3f;

void solve() {
    int n;
    cin >> n;

    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }

    vector<array<int, 20>> s(n + 1);
    for (int j = 0; j < 20; j++) {
        for (int i = 1; i <= n; i++) {
            s[i][j] = s[i - 1][j] + (a[i] >> j & 1);
        }
    } 

    auto check = [&](int k)->bool {
        for (int j = 0; j < 20; j++) {
            for (int i = k + 1; i <= n; i++) {
                if (!!(s[i][j] - s[i - k][j]) != !!(s[i - 1][j] - s[i - 1 - k][j])) {
                    return false;
                }
            }
        }
        return true;
    };

    int l = 1, r = n;
    while (l < r) {
        int mid = l + r >> 1;
        if (check(mid)) {
            r = mid;
        } else {
            l = mid + 1;
        }
    }

    cout << l << '\n';
}

void prework() {
}

int main() {
    cctie;

    prework();

    int T;
    cin >> T;

    while (T--) {
        solve();
    }

    return 0;
}

C. Cat, Fox and Double Maximum

贪心

注意到 \(n\) 位偶数,则显然答案的最大值不超过 \(\frac{n}{2}-1\),而这一值总是可以通过以下构造方式实现的。看 \(p\) 排列中 \(n\) 所处位置的奇偶性(可以避免最小值和最大值相邻的情况),若为奇数,则考虑对所有不位于两端且下标位奇数的位置作为山峰(即极大值)去构造,这些位置对应于 \(q\) 排列中的值应贪心的赋予,最小的赋予最大的,以此类推,这样最有可能在该位置构成山峰,而山峰两侧的值则是再不阻碍山峰的前提下赋予尽可能大的值,最后把未放数的位置用剩余的数补充即可;若为偶数,构造方法类似。

时间复杂度: \(O(nlogn)\) 。

#include <bits/stdc++.h>

using namespace std;

#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()

using i64 = long long;
using i128 = __int128;

const int INF = 0x3f3f3f3f;

void solve() {
    int n;
    cin >> n;

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

    vector<int> ord(n + 1);
    iota(ALL(ord), 1);
    sort(ALL(ord), [&](int i, int j){return p[i] < p[j];});

    set<int> S;
    for (int i = 1; i <= n; i++) {
        S.insert(i);
    }
    bool odd = (ord[n] & 1);

    vector<int> q(n + 1);
    for (int ii = 1; ii <= n; ii++) {
        int i = ord[ii];
        if (odd) {
            if ((i & 1) && i != 1) {
                q[i] = *S.rbegin();
                S.erase(--S.end());
            }
        } else {
            if (!(i & 1) && i != n) {
                q[i] = *S.rbegin();
                S.erase(--S.end());                
            }
        }
    }

    if (odd) {
        for (int i = 2; i <= n; i += 2) {
            int x = INF;
            if (i != n) {
                x = min(x, p[i + 1] + q[i + 1]);
            }
            if (i != 2) {
                x = min(x, p[i - 1] + q[i - 1]);
            }
            auto it = --S.lower_bound(x - p[i]);
            q[i] = *it;
            S.erase(it);
        }
    } else {
        for (int i = 3; i <= n; i += 2) {
            int x = INF;
            if (i != n - 1) {
                x = min(x, p[i + 1] + q[i + 1]);
            }
            if (i != 1) {
                x = min(x, p[i - 1] + q[i - 1]);
            }
            auto it = --S.lower_bound(x - p[i]);
            q[i] = *it;
            S.erase(it);
        }
    }

    for (int i = 1; i <= n; i++) {
        if (!q[i]) {
            q[i] = *S.begin();
            S.erase(S.begin());
        }
    }

    for (int i = 1; i <= n; i++) {
        cout << q[i] << " \n"[i == n];
    } 
}

void prework() {
}

int main() {
    cctie;

    prework();

    int T;
    cin >> T;

    while (T--) {
        solve();
    }

    return 0;
}

D. Cat, Fox and Maximum Array Split

交互、思维

\(l\) 为 \(1\), \(x\) 从 \(n^2\) 枚举到 \(n\) 去询问,当返回值为 \(n\) 时,则得出了数组中最大值 \(mx\),这样的询问最多进行了 \(n\) 次。接着我们知道,答案 \(m\) 存在的情况下,一定为 \(mx\) 的倍数,因为最大值也一定属于划分后 \(k\) 个子数组的某一个,所以我们只需要枚举 \(m\) 的值并判断是否可行即可,从 \(\frac{n}{k}*mx\) 枚举到 \(mx\),也就是枚举了 \(\frac{n}{k}\) 次,而每次判断也只需要最多 \(k\) 次询问,所以这样的询问也最多进行了 \(n\) 次,所以总次数最多进行了 \(2n\) 次。特别注意在输出答案后也要读取一个值。

时间复杂度: \(O(n)\)。

#include <bits/stdc++.h>

using namespace std;

#define cctie ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define all(x) x.begin(), x.end()
#define ALL(x) x.begin() + 1, x.end()

using i64 = long long;
using i128 = __int128;

const int INF = 0x3f3f3f3f;

void solve() {
    int n, k;
    cin >> n >> k;

    auto query = [&](int l, int x)->int {
        cout << "? " << l << " " << x << endl;
        int r;
        cin >> r;
        return r;
    };

    int mx = n;
    while (query(1, n * mx) != n) {
        mx--;
    }

    auto check = [&](int m)->bool {
        int cur = 0;
        for (int i = 0; i < k; i++) {
            if (cur == n) {
                return false;
            }
            int pos = query(cur + 1, m);
            if (pos == n + 1) {
                return false;
            }
            cur = pos;
        }
        return cur == n;
    };

    auto output = [&](int m)->void {
        cout << "! " << m << endl;
        int r;
        cin >> r;
    };

    for (int t = n / k; t >= 1; t--) {
        int m = t * mx;
        if (check(m)) {
            output(m);
            goto over;
        }
    }
    output(-1);
    over:
}

void prework() {
}

int main() {
    cctie;

    prework();

    int T;
    cin >> T;

    while (T--) {
        solve();
    }

    return 0;
}

标签:return,int,945,Codeforces,cin,using,Div,ldots,define
From: https://www.cnblogs.com/xiojoy/p/18199430

相关文章

  • Codeforces Round 945 (Div. 2)
    A-ChessForThree因为序列满足a<=b<=c的情况显然通过得分可以观察出得分总和必定为偶数否则不成立求的是最大平局数那么直接假设全部都是平局这时候发现如果c过大会导致后面的局数不是平局那么只用把c>a+b的情况取出而此时平均数为a+b点击查看代码#include<bits/stdc+......
  • Codeforces 769B News About Credit 题解
    题目简述波利卡普在由$n$名学生(包括他自己)组成的小组中学习,编号为$1$到$n$,波利卡普的编号始终是$1$。他们都在社交网络上注册,每个学生都有一个值$a_i$,表示第$i$名学生每天能发送的最大信息数。清晨,波利卡普知道了一个重要消息,他认为有必要通过私人消息紧急通知所有组员......
  • CF-945(已更A,B)
    CF-945(A,B)A分析模拟合法情况下三个数的和只能是偶数:题中的两种操作显然都不会改变和的奇偶性这点我的代码中没有用到要使平局数最多,一定是最大的两个数减一,重复这个过程,直到两个较小的数都为零,且最大数一定是偶数,否则不合法:可以由题意和样例想到代码inta[4];voidso......
  • Codeforces 959B Mahmoud and Ehab and the message 题解
    题目简述小A想要给他的朋友小B发送了一条有$m$个单词的消息。他们的语言由编号从$a_1$到$a_n$的$n$个单词组成。一些单词具有相同的意思,因此存在$k$个单词组,其中每个组中的所有单词具有相同的意思。小A知道第$i$个单词可以以成本$m_i$发送。对于他的每个消息......
  • Codeforces 1113B Sasha and Magnetic Machines 题解
    题目简述有一个长度为$n$的正整数序列。你可以对这个数列进行最多$1$次的如下操作:选择两个数$i$和$j$,其中$1\leqi,j\leqn$并且$i\neqj$,并选择一个可以整除$a_i$的正整数$x$,然后将$a_i$变为$\frac{a_i}{x}$,将$a_j$变为$a_j\cdotx$。问你操作后,该序......
  • Codeforces 1178B WOW Factor
    题目简述给定一个只含$v$和$o$的字符串$s$,求字符串中有多少个$wow$(一个$w$即为连续的两个$v$)。题目分析考虑枚举每一个$o$,设下标为$i$,统计它左边和右边各有多少个$w$,分别设为$a_{i-1}$和$b_{i+1}$,依据乘法原理,将它们乘起来即为答案,累加即可。接下来,考虑怎么处......
  • Codeforces 1037C Equalize 题解
    题目描述给定两个长度为$n$的$01$序列$a,b$。每次可以执行如下操作:在$a$中选择一个位置$p$,将$a_p$变为$1-a_p$,代价是$1$。在$a$中选择两个位置$p,q$,将$a_p$和$a_q$互换,代价是$\lvertq-p\rvert$。问最少需要多少代价才能将$a$变成$b$。题目分析......
  • 「比赛总结」CF Round 834 Div.3 比赛总结
    比赛链接最后AC了\(6\)题。首先开局拼手速过了前三题。然后一眼没有瞪出来D,就写了个随机化,然后交上去发现TLEontest#3,发现随机化的时候阙值取太大了,然后就把阙值改小了,然后交上去发现WAontest#3,这也太不牛了吧!于是赶紧跳了。然后看到E,这不是个傻逼题吗?严格小于......
  • D. Deleting Divisors
    https://codeforces.com/contest/1537/problem/D题意:给定数n,alice和bob博弈,alice先手。每次操作可以减去当前n的一个因子,并且该因子不能为n和1。问谁必胜。思路:策略分析。基础分析:如果n是奇数,那么没有偶数因子。如果n是偶数,可能有偶数因子和奇数因子,如果只有偶数因子,n是2的整数......
  • Codeforces 1004B Sonya and Exhibition 题解
    题目简述让你构造一个长度为$n$的$01$字符串。一个区间的价值为其中$0$的数量乘以$1$的数量,给出$m$个区间,最大化它们的价值之和。题目分析设区间$[l,r]$中$1$有$x$个,$0$有$y$个,当$x$和$y$最接近的时候,$x\timesy$最大,此结论可以用二次函数进行证明。......