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

Codeforces Round #879 (Div. 2) A-E

时间:2023-06-24 17:33:51浏览次数:58  
标签:879 int Codeforces long solve 区间 using Div LCM

比赛链接

A

代码

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

bool solve() {
    int n;
    cin >> n;
    int cnt = 0;
    for (int i = 1;i <= n;i++) {
        int x;
        cin >> x;
        if (x == -1) cnt++;
    }
    int diff = max(0, (2 * cnt - n + 1) / 2);
    cout << diff + ((cnt - diff) % 2 == 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;
}

B

代码

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

bool solve() {
    string a, b;
    cin >> a >> b;
    int n = max(a.size(), b.size());
    a = "?" + string(n - a.size(), '0') + a;
    b = "?" + b;
    int ans = 0;
    for (int i = 1;i <= n;i++) {
        if (a[i] != b[i]) {
            ans += b[i] - a[i] + 9 * (n - i);
            break;
        }
    }
    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;
}

C

题目

给两个串 \(S,T\) ,AB轮流操作,A先操作。

A:选一个串,选择其中一个位置,修改成任意想要的字符。

B:选择一个串,反转他。

问最少操作几次,使得 \(S=T\) 。

题解

知识点:贪心。

显然,B不会修改字符,并且操作两次等于没操作。

因此,关键在于A的两种情况的操作次数:

  1. 把两个字符串的对应位置修改成一样。
  2. 反转其中一个后,把两个字符串的对应位置修改成一样。

这两种情况,对B的要求:

  1. 前者需要B操作偶数次,因此若A的操作次数是奇数,那么B要减一次操作。
  2. 后者需要B操作奇数次,因此若A的操作次数是偶数,那么B要减一次操作。注意这种A可能操作 \(0\) 次,此时通过前面计算得出的是 \(-1\) 是不合法的,为了方便我们对前面的结果与 \(2\) 取最大值即可。

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

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

代码

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

bool solve() {
    int n;
    cin >> n;
    string s, t;
    cin >> s >> t;
    s = "?" + s;
    t = "?" + t;
    int cnt1 = 0, cnt2 = 0;
    for (int i = 1;i <= n;i++) {
        cnt1 += s[i] == t[i];
        cnt2 += s[i] == t[n - i + 1];
    }
    int ans1 = 2 * (n - cnt1) - ((n - cnt1) & 1);
    int ans2 = max(2, 2 * (n - cnt2) - (!((n - cnt2) & 1)));
    cout << min(ans1, ans2) << '\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

题目

在 \([1,m]\) 上给定 \(n\) 个区间 \([l_i,r_i]\) 。

可以选择 \([1,m]\) 中若干个不同数字,那么每个区间的值为区间出现的所选数字个数减去剩余的所选数字个数。

问如何选择数字,使得选择后区间值的最大值与最小值的差值最大。

题解

知识点:枚举,贪心。

考虑枚举每个区间作为最大值,对于一个区间 \(A\) 作为最大值,即选择其中所有数字。此时,对于其他任意一个区间 \(B\) ,\(A\) 与 \(B\) 的区间值的差值为 \(|A| - (|A \cap B|- (|A|-|A \cap B|)) = 2(|A| - |A \cap B|)\) ,等价于我们要选择一个 \(B\) ,最大化 \(A\) 不在 \(B\) 中的部分,考虑三种情况以及对应的方案:

  1. \(B\) 在 \(A\) 中或 \(A\) 在 \(B\) 中,我们要找到最短的 \(|B|_{min}\) ,则差值最大值为 \(|A| - |B|\) 。
  2. \(B\) 与 \(A\) 的左侧相交,我们要找到最小的右端点 \(minR\) ,则差值最大值为 \(r_i - minR\)。
  3. \(B\) 与 \(A\) 的右侧相交,我们要找到最大的左端点 \(maxL\),则差值最大值 \(maxL - l_i\) 。

更进一步,我们可以得到,对于一个 \(B\) ,无论 \(B\) 属于上面哪一种情况,三种方案只会有一个会得到最大值。因此, \(A\) 与 \(B\) 的关系并不重要,我们不需要每次对一个特定的 \(A\) 将所有的 \(B\) 按三种情况分类后分别求解,而是可以无视 \(A\) 是什么,直接对所有 \(B\) 采取三种方案,其中总会有一个正确的最大值。

既然如此,那么我们事先得到所有区间的最短长度、最小右端点、最大左端点,随后枚举每个区间作为最大值区间 \(A\) ,直接使用它们计算答案取最大值即可,如此会方便很多。

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

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

代码

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

int L[100007], R[100007];
bool solve() {
    int n, m;
    cin >> n >> m;
    int minlen = 2e9, maxlen = 0;
    for (int i = 1;i <= n;i++) {
        cin >> L[i] >> R[i];
        minlen = min(minlen, R[i] - L[i] + 1);
        maxlen = max(maxlen, R[i] - L[i] + 1);
    };
    int maxL = *max_element(L + 1, L + n + 1);
    int minR = *min_element(R + 1, R + n + 1);
    int ans = maxlen - minlen;
    for (int i = 1;i <= n;i++) ans = max(ans, min(R[i] - L[i] + 1, max(maxL - L[i], R[i] - minR)));
    cout << 2 * 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;
}

E

题目

给一个有 \(n\) 个数的数组 \(a\) ,问最小的 \(x\) 使得 \(x\) 不等于 \(a\) 任意子区间的 \(\text{lcm}\) 。

题解

知识点:GCD和LCM,线性dp,枚举。

问题等价于找到全部子区间LCM的MEX,即第一个未出现的数字。

全部子区间的LCM种类不会超过 \(n^2\) 个,因此其MEX大小不会超过 \(n^2\) ,我们只需要求出不大于 \(n^2\) 的LCM即可,超过的 \(n^2\) 的LCM可以断定是无效的。

我们考虑固定子区间右端点,对于任意左端点,设子区间产生不同的LCM为 \(x_1 < \cdots < x_k\) 。同时,因为是固定了右端点,因此大的子区间的LCM一定是小的子区间的LCM的倍数,有不等式 \(x_i \geq 2x_{i-1}, i = 2,3,\cdots,k\) ,于是我们有 \(n^2 \geq x_k \geq 2^{k-1}\) ,所以 \(k\leq 1+ 2\log_2n\) 。

通过上述方法,我们可以得到每次迭代中,枚举的LCM不超过 \(1+ 2\log_2n\) ,总的LCM不超过 \(n(1+2\log_2n)\) 。因此,我们这个方法得到全部有效的LCM的复杂度是 \(O(n \log n)\) 的。当然,我们需要用 set 维护不同种类,所以最终复杂度是 \(O(n \log^2 n)\) 。

更进一步地,LCM总种类数 \(n(1+2\log_2n)\) 又可以反过来推断出MEX大小的不会超过 \(n(1+2\log_2n)\) ,这个大小在这道题不超过 \(2 \times 10^7\) ,因此可以用一个 int 范围的数限制大小。

时间复杂度 \(O(n \log^2 n)\)

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

代码

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

int a[300007];
bool solve() {
    int n;
    cin >> n;
    for (int i = 1;i <= n;i++) cin >> a[i];

    set<int> st, pre;
    for (int i = 1;i <= n;i++) {
        set<int> now;
        now.insert(a[i]);
        for (auto x : pre) {
            ll y = lcm((ll)x, a[i]);
            if (y <= 2e6) now.insert(y);
        }
        for (auto x : now) st.insert(x);
        swap(pre, now);
    }
    int ans = 1;
    while (st.count(ans)) ans++;
    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;
}

标签:879,int,Codeforces,long,solve,区间,using,Div,LCM
From: https://www.cnblogs.com/BlankYang/p/17501380.html

相关文章

  • Codeforces Round 781 (Div. 2) E. MinimizOR (可持久化字典树)
    传送门题目大意:  T组测试数据每组测试数据先输入一个n表示有一个长度为n的一维数组,然后输入n个数字表示这个一维数组。紧接着输入一个k表示有k个询问,对于每个询问会输入一个l和一个r表示询问数组中[l,r]这个区间里面任意两个下标不重复的元素最小的或(|)是多少。解题思路: ......
  • Codeforces Round 881 (Div
    E.TrackingSegments给定初始长度为n,且全为0的序列a,然后给出m个线段,如果一个线段中1的个数严格大于0的个数,那么该线段称为一个漂亮线段,现在给出q次操作,每次操作使得序列a中位置x上的0变为1,请你求出第一次使得所有线段中出现漂亮线段的询问题解:二分答案容易发现答案具有单......
  • Codeforces 1603D. Artistic Partition
    题目链接:D-ArtisticPartition题目大意:要求将\([1,n]\)分成\(k\)段,使得每段对应的\(c(l,r)\)之和最小,其中\(c(l,r)=\sum_{i=l}^r\sum_{j=i}^r[\gcd(i,j)\gel]\)。首先注意到当\(r<2l\)时,\(c(l,r)=r-l+1\)。所以当\(2^k-1\gen\)时答案即为\(n\)。考虑\(\texttt......
  • Codeforces Round 766 (Div. 2) 比赛报告
    0比赛经过比赛还没开始的时候就感觉状态不太好。果然。总归到底都是一个心态问题。A题经过看A题,结果半天看不懂,一开始没有注意到一定要在黑格子上操作。扔到DeepL上翻译了一下,再手玩一下样例就做出来了,速度有点慢。CF怎么这么喜欢出分讨题啊。看题目不能太急,要一个一......
  • Codeforces Round 881 (Div. 3)--F2
    F2.OmskMetro(hardversion)#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;#defineendl"\n"#defineintlonglongconstintN=2e5+5;constintINF=0x3f3f3f3f;//假设一个区间的最大字段和为max最小字段和为min//那么[min,max]区间的......
  • 鼠标悬浮div或者列表li时,展示出button按钮
    <template><divclass="item"><span><inputtype="checkbox":checked="obj.done"@click="handleCheck(obj.id)"></span><span>{{......
  • Codeforces 1835F - Good Graph
    goodproblem,badround。判断YES还是NO很trivial,就直接跑最大匹配看看是不是\(n\)即可。如果是NO,那么考虑Hall定理的证明过程构造即可。具体方法就是找到左部任意一非匹配点,在残量网络上BFS可以到达的点,那所有可以到达的左部点形成的集合就是符合要求的反例。因为你......
  • Codeforces 1835E - Old Mobile
    首先先观察到一个非常浅显的性质:就是一个位置在序列中不是第一次出现,那么到这个位置的时候打出这个字符需要恰好一次按键,这是因为我们肯定在打出第一次出现这个字符的位置的时候已经知道哪个键对应这个字符了,到那个位置的时候直接敲一下就ok了。也就是我们只用关心这个序列中出......
  • Codeforces Round 878 (Div. 3) D. Wooden Toy Festival
    题目翻译:给定一个序列,你可以把序列分为任意的三组不要求顺序,对于每一组序列给出一个数字作为标准,求出序列中和该数字的差绝对值的最大值,现在要求你选顶三个数字使得三个序列的差最大值的最大值最小解题思路:二分,要想方差最小,就让每一组的极差都最小,即最大值减最小值最小#include......
  • 练习记录-cf-Codeforces Round 881 (Div. 3)A-F1
    E是补的太蠢了没想到期末考完的复健A.SashaandArrayColoring题意:可以给不同数字涂上很多颜色,每个颜色的贡献是同一个颜色内的数字最大值和最小值的差思路:排序一遍,取头和尾的差#include<bits/stdc++.h>#defineclosestd::ios::sync_with_stdio(false),cin.tie(0)......