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

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

时间:2023-07-13 19:25:57浏览次数:37  
标签:node 882 cnt int Codeforces long using Div bit

比赛链接

A

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int a[107];
int f[107];
bool solve() {
    int n, k;
    cin >> n >> k;
    for (int i = 1;i <= n;i++) cin >> a[i];
    for (int i = 1;i <= n - 1;i++) f[i] = abs(a[i + 1] - a[i]);
    sort(f + 1, f + n);
    int sum = 0;
    for (int i = 1;i <= n - k;i++) sum += f[i];
    cout << sum << '\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

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

bool solve() {
    int n;
    cin >> n;
    int sum = ~(1 << 31), cnt = 0;
    for (int i = 1;i <= n;i++) {
        int x;
        cin >> x;
        sum &= x;
        if (sum == 0) cnt++, sum = ~(1 << 31);
    }
    cout << max(cnt, 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;
}

C

题意

开始时有 \(n\) 个数,每次操作可以取一个后缀异或和放到所有数后面,问能取到的最大数字是多少。

题解

方法一

知识点:位运算,字典树。

我们发现,无论我们怎么取,取到的值一定是原来 \(n\) 个数字的一个连续段的异或和,因此问题变成求最大子段异或和。

最大子段异或和非常经典,可以用01Trie解决。

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

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

方法二

知识点:位运算,枚举。

这里只有 \(2^8\) ,所以也可以枚举。

时间复杂度 \(O(n2^8)\)

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

代码

方法一

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

class Trie {
    struct Node {
        array<int, 2> nxt;
        int val;
    };

    int bit;
    vector<Node> node;
    Node NIL;

public:
    Trie(int _bit = 0) { init(_bit); }

    void init(int _bit) {
        bit = _bit;
        NIL = { {0,0},0 };
        node.assign(1, NIL);
    }

    void insert(int s) {
        int p = 0;
        for (int i = bit - 1;i >= 0;i--) {
            int c = (s >> i) & 1;
            if (!node[p].nxt[c]) {
                node[p].nxt[c] = node.size();
                node.push_back(NIL);
            }
            p = node[p].nxt[c];
        }
        node[p].val = s;
    }

    int find(int s) {
        int p = 0;
        for (int i = bit - 1;i >= 0;i--) {
            int c = (s >> i) & 1;
            if (node[p].nxt[c ^ 1]) p = node[p].nxt[c ^ 1];
            else p = node[p].nxt[c];
        }
        return node[p].val;
    }
};

int a[100007];
bool solve() {
    int n;
    cin >> n;
    for (int i = 1;i <= n;i++) cin >> a[i];
    Trie trie(8);
    trie.insert(0);
    int sum = 0, ans = 0;
    for (int i = 1;i <= n;i++) {
        sum ^= a[i];
        ans = max(ans, sum ^ trie.find(sum));
        trie.insert(sum);
    }
    cout << ans << '\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;
}

代码二

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int a[100007];
bool solve() {
    int n;
    cin >> n;
    for (int i = 1;i <= n;i++) cin >> a[i];
    vector<int> vis(1 << 8);
    int sum = 0, ans = 0;
    vis[0] = 1;
    for (int i = 1;i <= n;i++) {
        sum ^= a[i];
        for (int j = 0;j < (1 << 8);j++)
            if (vis[j]) ans = max(ans, sum ^ j);
        vis[sum] = 1;
    }
    cout << ans << '\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

题意

给定一个长为 \(n\) 的 \(01\) 串 \(s\) ,取其 \(m\) 个子串 \(s[l_i,r_i]\) ,按取的顺序从左到右拼接得到 \(t(s)\) 。

在取子串前,可以执行一种操作:交换 \(s\) 中的两个不同位置的字符。

问最少需要执行多少次操作,才能使得 \(t(s)\) 是所有可能的结果中字典序最大的。

题解

知识点:并查集,树状数组,贪心。

显然,子串靠前的,位置在子串中靠前的,优先级更大。因此,按子串顺序,子串内从左到右,给 \(s\) 的位置规定排名 \(rk\) 。

排名中可能会遇到之前已经排名过的位置,这些位置的排名是不需要改变的,我们需要跳过它们。为了保证复杂度,可以用并查集实现跳转,当然也可以用 set

接下来,我们要尽可能把 \(1\) 交换到排名靠前的位置,因此我们需要知道 \(1\) 的总数 \(cnt\) ,以及排名前 \(cnt\) 个位置的 \(1\) 个数 \(sum[1,cnt]\) ,交换次数就是 \(cnt - sum[1,cnt]\) 。

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

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

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

template <class T>
class Fenwick {
    int n;
    vector<T> node;

public:
    Fenwick(int _n = 0) { init(_n); }

    void init(int _n) {
        n = _n;
        node.assign(n + 1, T());
    }

    void update(int x, T val) { for (int i = x;i <= n;i += i & -i) node[i] += val; }

    T query(int x) {
        T ans = T();
        for (int i = x;i >= 1;i -= i & -i) ans += node[i];
        return ans;
    }
    T query(int l, int r) {
        T ans = T();
        ans += query(r);
        ans -= query(l - 1);
        return ans;
    }

    int lower_bound(T val) {
        int pos = 0;
        for (int i = 1 << __lg(n); i; i >>= 1) {
            if (pos + i <= n && node[pos + i] < val) {
                pos += i;
                val -= node[pos];
            }
        }
        return pos + 1;
    }
    int upper_bound(T val) {
        int pos = 0;
        for (int i = 1 << __lg(n); i; i >>= 1) {
            if (pos + i <= n && node[pos + i] <= val) {
                pos += i;
                val -= node[pos];
            }
        }
        return pos + 1;
    }
};

struct DSU {
    vector<int> fa;

    DSU(int n = 0) { init(n); }

    void init(int n) {
        fa.assign(n + 1, 0);
        iota(fa.begin(), fa.end(), 0);
    }

    int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

    bool same(int x, int y) { return find(x) == find(y); }

    void merge(int x, int y) { fa[find(x)] = find(y); }
};

int idx;
int rk[200007];
int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    int n, m, q;
    cin >> n >> m >> q;
    string s;
    cin >> s;
    s = "?" + s;

    int cnt = count(s.begin() + 1, s.end(), '1');
    Fenwick<int> fw(n);
    DSU dsu(n + 1);
    for (int i = 1;i <= m;i++) {
        int l, r;
        cin >> l >> r;
        for (int j = dsu.find(l);j <= r;j = dsu.find(j)) {
            rk[j] = ++idx;
            if (s[j] == '1') fw.update(rk[j], 1);
            dsu.merge(j, j + 1);
        }
    }

    while (q--) {
        int x;
        cin >> x;
        if (s[x] == '0') {
            s[x] = '1';
            cnt++;
            if (rk[x]) fw.update(rk[x], 1);
        }
        else {
            s[x] = '0';
            cnt--;
            if (rk[x]) fw.update(rk[x], -1);
        }
        cout << min(cnt, idx) - fw.query(min(cnt, idx)) << '\n';
    }
    return 0;
}

标签:node,882,cnt,int,Codeforces,long,using,Div,bit
From: https://www.cnblogs.com/BlankYang/p/17551852.html

相关文章

  • codeforces1283F
    题目链接sol:根一定是第一个,然后不太会,去看了洛谷题解题解#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;typedefpair<int,int>pii;#definefifirst#definesesecond#definefz1(i,n)for((i)=1;(i)<=(n);(i)++)#definefd1(i,n)for((i)......
  • Educational Codeforces Round 151 (Rated for Div. 2)
    D.RatingSystem题目大意玩家的初始积分为0,该玩家连续进行\(n\)场比赛,每场比赛可升高或降低玩家的积分(\(a_i\))。你可以设置一个\(k\)值,比赛过程中玩家的积分不会低于\(k\)(若有一场比赛会使玩家的积分低于\(k\),比赛后玩家的积分会被强制变为\(k\))。找到一个\(k\),使经过\(n\)......
  • codeforces1311E
    题目链接sol:先建一条链,然后把下面的点一个个往上面移,优先移到最上面,如果上面满了就往下一层,知道刚刚好凑满距离,如果最后不能移了就说明不能凑出给定的距离#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;typedefpair<int,int>pii;#definefifir......
  • Codeforces Round 884 (Div. 1 + Div. 2)
    Preface究极坐牢场,比赛降智导致签到签挂,本来秒出的D写错一个极其傻逼的地方浪费半小时然后后面两个小时坐牢想E和F1,但可惜并没有看出E的性质,被狠狠地薄纱虽然说实话后面有点困了,但应该不至于写不出这个E的,只能说最近的状态真是堪忧啊A.SubtractionGame首先若\(a\ne1\)则......
  • Codeforces Round 884 (Div. 1 + Div. 2)
    A.SubtractionGame答案就是a+b此时后手必胜因为无论怎么操作后手都可保证自己取的时候一次全部取完#include<bits/stdc++.h>usingnamespacestd;voidsolve(){inta,b;cin>>a>>b;cout<<a+b<<"\n";return;}intmain(){......
  • codeforces-817 D. Imbalanced Array(单调栈)
    题意:求数组中每个连续子序列的的最大值-最小值之和。思路:题意可以理解为加上每一个序列的最大值,减去每一个序列的最小值。每个数都可以作为某一连续子序列的最大值和最小值,所以可以枚举每一个数作为最值的区间,暴力枚举时间复杂度过高,所以利用单调栈找出每个数左边或右边第一个比......
  • Codeforces Round 871 (Div. 4) ABCDEF
    很久没写题目了,划点水题A.LoveStory#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpair<LL,LL>PII;constLLMAXN=1e18;constLLN=1e6,M=4002;constLLmod=1e9+7;intmain(){//cin.tie(0);cout.tie(0);ios......
  • 「解题报告」Codeforces Round #884 (Div. 1 + Div. 2) Editorial
    比赛地址:Dashboard-CodeforcesRound884(Div.1+Div.2)-Codeforces个人评价:这场是构造专场!A.SubtractionGameProblem-A-Codeforces有一堆石子(应该是石子),每次只能拿走\(a\)块或者\(b\)块,最先不能移动的人输,构造一个数\(n\),使得先手必输。两种构造方法:......
  • CodeForces Gym 102900B Mine Sweeper II
    CF传送门感觉像脑筋急转弯。考虑所有数字之和就是相邻的\((\text{雷},\text{空地})\)对数,因此翻转后这个对数不会改变。然后由于抽屉原理,\(b\toa\)和\(b\to\operatorname{inv}(a)\)中至少有一个操作次数\(\le\left\lfloor\frac{nm}{2}\right\rfloor\),然后就做完了......
  • UESTC 2023 Summer Training #02 Div.2
    Preface都给我丑完了这怎么办啊,被血虐了苦路西这场本来前面感觉都还可以,但是当中期看了眼C的题意后准备开C后就不对劲了起来最后1h扔掉一直T的C题去做H,结果因为被卡自然溢出的Hash一直挂到比赛结束,直接红温感觉这场策略问题挺大的,比如没有跟榜去写更加简单的E题(比赛的时候题......