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

Codeforces Round #832 (Div. 2) A-D

时间:2022-11-05 09:56:41浏览次数:121  
标签:832 cout int 复杂度 Codeforces long 异或 solve Div

比赛链接

A

题解

知识点:贪心。

我们考虑把正数和负数分开放,显然把负数和正数放在一起的结果不会更优。

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

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

bool solve() {
    int n;
    cin >> n;
    ll sum1 = 0, sum2 = 0;
    for (int i = 1;i <= n;i++) {
        int x;
        cin >> x;
        if (x >= 0) sum1 += x;
        else sum2 += -x;
    }
    cout << max(sum2 - sum1, sum1 - sum2) << '\n';;
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}

B

题解

知识点:构造。

为了破坏每个子序列,我们把 B 扔到最后面即可,但这样太麻烦,还要考虑跳过后面本来就有的 B

因此我们选择首末 BN 交换,这样只需要进行一半的对称操作。

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

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

bool solve() {
    int n;
    cin >> n;
    cout << (n + 1) / 2 << '\n';
    for (int i = 1, j = 3 * n;i < j;i += 3, j -= 3) {
        cout << i << ' ' << j << '\n';
    }
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}

C

题解

知识点:博弈论。

如果 \(\forall i\in [2,n]\) 都有 \(a_1\leq a_i\) ,A 无论怎么取,不妨假设取了下标 \(i\) ,只要 B 取相同下标的,就会导致 \(a_1-1 \cdots a_i-1\cdots\) ,回到这种局面,并且数字减一,往复如此, \(a_1\) 会在 A 的回合是 \(0\) 于是输了。

如果 \(\exist i\in[2,n]\) 有 \(a_1>a_i\) ,A 取 \(a_i\) 中最小的那个,就到了 \(\forall i\in [2,n]\) 都有 \(a_1\leq a_i\) 但 B 先手的局面,B 输。

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

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

int a[100007];
bool solve() {
    int n;
    cin >> n;
    for (int i = 1;i <= n;i++) cin >> a[i];
    bool ok = 0;
    for (int i = 2;i <= n;i++) {
        ok |= a[1] > a[i];
    }
    cout << (ok ? "Alice" : "Bob") << '\n';
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}

D

题解

知识点:贪心,枚举,STL,前缀和。

几个结论:

  1. 操作的区间不会交叉。因为交叉一定可以合并成一个完整的区间操作,答案不变,所以操作一定是互不相交的。
  2. 区间能操作至 \(0\) 的必要条件是异或和为 \(0\) 。因为操作本质是异或和,能合并,如果操作可行则合并得到整个区间的异或和也是 \(0\) 。

考虑处理出前缀和,和前缀异或和方便计算。在满足必要条件下分类讨论,不满足的无解:

  1. 区间全是 \(0\) ,不需要操作。

  2. 否则,区间长度为奇数,整个操作一次。

  3. 否则,若首或尾有 \(0\) 元素,则可以拆一个出来得到情况2,操作一次即可。

  4. 否则,找到区间内某个分割点,使得区间划分成两个长度为奇数异或和为 \(0\) 的区间,回到情况2,操作两次即可。

    注意,不需要考虑划分成两个偶数长度区间,如果有偶数长度划分可行,则一定分别能再被划分成两个奇数长度区间,即得到四个奇数长度异或和为 \(0\) 的区间,取前 \(3\) 个合并最后变成两个奇数区间,因此一定存在奇数划分。

  5. 其他情况无解。

最后考虑情况4如何找到划分点。我们用 map 记录到 \(i\) 之前所有出现的异或和最后一次出现的位置,分奇数下标偶数下标分别记录。那么对于一个位置 \(i\) ,我们就能找到左侧最近的一个不同奇偶性的位置 \(last[i]\) ,使得 \([1,i]\) 和 \([1, last[i] ]\) 的异或和相同,且 \((last[i],i]\) 区间长度为奇数,于是我们就找到了一个划分点。如果划分点小于 \(l\) 则不可划分。

时间复杂度 \(O(n \log n + q)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

int a[200007], xsum[200007], last[200007];
ll sum[200007];
bool solve() {
    int n, q;
    cin >> n >> q;
    for (int i = 1;i <= n;i++) {
        cin >> a[i];
        sum[i] = sum[i - 1] + a[i];
        xsum[i] = a[i] ^ xsum[i - 1];
    }
    map<int, int> mp[2];
    for (int i = 1;i <= n;i++) {
        if (mp[!(i & 1)].count(xsum[i])) last[i] = mp[!(i & 1)][xsum[i]];
        mp[i & 1][xsum[i]] = i;
    }
    while (q--) {
        int L, R;
        cin >> L >> R;
        if ((xsum[R] ^ xsum[L - 1]) == 0) {
            if (sum[R] - sum[L - 1] == 0) cout << 0 << '\n';
            else if ((R - L + 1) & 1 || !a[L] || !a[R]) cout << 1 << '\n';
            else if (last[R] >= L) cout << 2 << '\n';
            else cout << -1 << '\n';
        }
        else cout << -1 << '\n';
    }
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    //cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}

标签:832,cout,int,复杂度,Codeforces,long,异或,solve,Div
From: https://www.cnblogs.com/BlankYang/p/16859683.html

相关文章

  • Codeforces Round #832 (Div. 2)
    A.TwoGroups数组和的绝对值即为答案。B.BANBAN大概就是尽可能把前面的B搞到后面,尽可能把后面的N搞到前面。答案为\(\lceil\frac{n}{2}\rceil\),操作为每次......
  • Codeforces Round #764 (Div. 3) G
    G.MinOrTree看到或运算我们思考如何按位来做我们可以贪心的从高位到低位的要是该位可以都用0的来构成一颗生成树我们显然是很高兴的但是怎么check?我们每次遍历一......
  • CodeForces - 914C Travelling Salesman and Special Numbers
    题意:给出一个二进制数a,每次操作将当前数变成其二进制下1的个数,若干次操作后可以将其变为1.给定k,求不大于a的数中,经过k次操作能变成1的数的数量。解:观察一下这个操作,可以求......
  • Codeforces Round #776 (Div. 3) E
    E.ReschedulingtheExam显然我们能想到的每次操作都是先将最小的取出来操作要是我们有两个数都是最小的我们只有相邻的时候才能操作要是大于两个那我们就不管怎么操......
  • Codeforces Round #778 (Div. 1 + Div. 2, based on Technocup 2022 Final Round) F M
    A-E都还是比较简单的。首先,容易想到的,异或上\(2^k\),相当于以\(2^{k+1}\)的长度分块,然后每一块对半切,然后交换左右部分。我的想法是由于这个交换的性质,也许我们可以尝......
  • Codeforces Round #766 (Div. 2)
    CodeforcesRound#766(Div.2)\(\color{Green}{★}\)表示赛时做出。\(\color{Yellow}{★}\)表示赛后已补。\(\color{Red}{★}\)表示\(\text{To\be\solved}\)......
  • Codeforces Round #820 (Div. 3) F
    F.KireiandtheLinearFunction首先我们知道的是给定长度w都是%9意义下的所以我们枚举四个位置的数就是9^4预处理出来答案这里我们要去w长度的串%9但是w的位数过......
  • Codeforces Global Round 20 D F1 F2/more
    https://codeforc.es/contest/1672F1https://www.luogu.com.cn/blog/AlexWei/solution-cf1672f1将置换分解为若干轮换(环),悲伤值越大\(\Rightarrow\)环越少(设环为\(k......
  • Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2) D
    D.ExplorerSpace我们考虑一个性质就是他最多就是找到一条k/2的最短路径然后回来这样是肯定是包含最优解的这个观察第二个样例我们将其改变一下要是我们一半的长度......
  • CodeForces 1540B Tree Array
    CF传送门洛谷传送门很强的一个题。发现根的选择很重要,于是考虑先枚举根。考虑枚举两个点对\(i,j\(i<j)\),如果\(j\)比\(i\)先被标记,那么\(i,j\)就贡献了一个逆......