首页 > 其他分享 >CodeForces Round #959 sponsored by NEAR (Div. 1 + Div. 2) 补题记录(A~E)

CodeForces Round #959 sponsored by NEAR (Div. 1 + Div. 2) 补题记录(A~E)

时间:2024-07-20 11:06:57浏览次数:14  
标签:959 const int cin long -- while 补题 Div

简单场.png

A

若 \(n\times m=1\) 则显然无解。否则因为 \(a\) 矩阵是一个 \(n\times m\) 的排列,所以说只需要让其循环右移一位即可。

时间复杂度 \(O(nm)\)。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[233][233];
signed main() {
    int T;
    cin >> T;
    while (T--) {
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j)
                cin >> a[i][j];
        if (n == 1 && m == 1)
            puts("-1");
        else {
            for (int i = 1; i <= n; ++i) {
                for (int j = 1; j <= m; ++j) {
                    int v;
                    if (j != m) v = a[i][j + 1];
                    else if (i != n) v = a[i + 1][1];
                    else v = a[1][1];
                    cout << v << ' ';
                }
                cout << '\n';
            }
        }
    }
    return 0;
}

B

手模几组数据之后可以发现:

  • 若两个字符串已经相等则一定成立。
  • 若两个字符串不相等,则令 \(s\) 串中第一个是 \(1\) 的位置 \(p_1\),\(t\) 串中第一个是 \(1\) 的位置 \(p_2\)。若有 \(p_1\le p_2\) 则有解,否则无解。

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

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[233][233];
signed main() {
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        string s, t;
        cin >> s >> t;
        if (s == t)
            puts("Yes");
        else {
            for (int i = 0; i < n; ++i) {
                if (s[i] == '1') {
                    puts("Yes");
                    break;
                } else if (t[i] == '1') {
                    puts("No");
                    break;
                }
            }
        }
    }
    return 0;
}

C

简单 dp 题。正着做不好处理,考虑倒着做。

设 \(f_i\) 表示若左端点 \(l=i\) 的时候,不同满足条件的 \(r\) 的数量。则:

  • 若 \(a_i>x\) 则 \(f_i=f_{i+1}\)。
  • 若 \(\sum\limits_{j=i}^n a_j\le x\) 则 \(f_i=n-i+1\)。
  • 否则令 \(p\) 为最小的满足 \(\sum\limits_{j=i}^p a_j>x\) 的位置 \(p\)。则有 \(f_i=p-i+f_{p+1}\)。

前面两个转移都是容易的,第三个转移直接维护一下前缀和,然后二分找到 \(p\) 即可。

时间复杂度为 \(O(n\log n)\)。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[N], s[N], f[N];
signed main() {
    int T;
    cin >> T;
    while (T--) {
        int n, x;
        cin >> n >> x;
        for (int i = 1; i <= n; ++i)
            cin >> a[i], s[i] = s[i - 1] + a[i];
        f[n + 1] = f[n + 2] = 0;
        int sum = 0;
        for (int i = n; i; --i) {
            int l = i, r = n, best = -1;
            while (l <= r) {
                int mid = l + r >> 1;
                if (s[mid] - s[i - 1] <= x)
                    best = mid, l = mid + 1;
                else
                    r = mid - 1;
            }
            if (best == -1)
                sum += (f[i] = f[i + 1]);
            else
                sum += (f[i] = best - i + 1 + f[best + 2]);
        }
        cout << sum << '\n';
    }
    return 0;
}

D

考虑倒着处理。首先若 \(a_i=a_j\) 则 \(|a_i-a_j|=0\),直接把这些边给连接。

然后对于剩下的一些倍数关系。若当前枚举的倍数关系为 \(d\),则按照 \(a_i\bmod d\) 的值将当前所有的 \(a_i\) 分为 \(d\) 类。然后随便找到两个 \(i\) 满足它们都在同一类里面,且当前没有连通,并将它们连通。判断两个点是否连通可以使用并查集。

时间复杂度为 \(O(\alpha n^2)\)。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 500100;
int a[N], fa[N];
vector<int> b[N];
int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}
signed main() {
    srand(time(0));
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        for (int i = 1; i <= n; ++i)
            cin >> a[i], fa[i] = i;
        map<int, int> mp;
        vector<pair<int, int>> res;
        for (int i = 1; i <= n; ++i) {
            if (mp.count(a[i])) {
                int t = mp[a[i]], v = i;
                res.emplace_back(t, v);
                fa[find(t)] = find(v);
            }
            else
                mp[a[i]] = i;
        }
        for (int i = n - 1 - res.size(); i; --i) {
            for (int j = 0; j < i; ++j)
                b[j].clear();
            for (int j = 1; j <= n; ++j)
                b[a[j] % i].emplace_back(j);
            for (int j = 0; j < i; ++j)
                for (int k = 1; k < b[j].size(); ++k) {
                    int A = b[j][0], B = b[j][k];
                    if (find(A) != find(B)) {
                        fa[find(A)] = find(B);
                        res.emplace_back(A, B);
                        goto ee;
                    }
                }
            ee:;
        }
        reverse(res.begin(), res.end());
        if (res.size() == n - 1) {
            puts("Yes");
            for (auto &[u, v] : res)
                cout << u << ' ' << v << '\n';
        } else {
            puts("NO");
        }
    }
    return 0;
}

E

首先每一次可以挪动一个树的任意一个叶子结点,这样每一次操作树的大小都会减去一。因此一个大小为 \(p\) 的树一定可以给出 \(1\sim p\) 中任意一个整数的贡献。

此时可以发现,若对于两个树满足它们的大小分别为 \(l_1\),\(l_2\),且 \(l_1\le l_2\),那么 \(l_1\) 所对应的树能得到的贡献,\(l_2\) 也一定能得到。

然后考虑贪心。因为是位运算所以考虑按位处理答案。设当前枚举到了第 \(i\) 位。则考虑暴力枚举每一个树,若当前的树的大小超过了 \(2^i\),则这个树可以胜任这个代价。因为还有后面的情况所以考虑尽量贪心的在能胜任的前提下找到树大小最小的树。这个东西可以暴力排序然后去找。因为每一次只更新了一个树的大小,所以排序可以暴力做。

问题是这样贪心有可能并不优秀。例如说只有一个大小为 \(6\) 的树,形如:

pkTdKG8.png

则通过删除任意两个叶子结点操作获得 \(4\) 的贡献之后,若需要找 \(2\) 的贡献,则发现树上没有 \(2\) 的贡献可用。

此时考虑反悔贪心。直接在树上获取 \(4+2=6\) 的贡献(即一次删除一个树),此时需要保证树还足够删除。这样就可以保证贪心始终优秀了。

时间复杂度为 \(O(n\log n)\),具体的细节可以看代码。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000100;
int a[N];
signed main() {
    srand(time(0));
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i];
            for (int j = 1; j < a[i]; ++j) {
                int t;
                cin >> t;
            }
        }
        sort(a + 1, a + n + 1);
        int bit = 0;
        for (int i = 20; ~i; --i) {
            int id = -1;
            for (int j = 1; j <= n; ++j)
                if (a[j] >= (1ll << i)) {
                    bit |= (1ll << i);
                    a[j] -= (1ll << i);
                    id = j;
                    break;
                }
            if (~id && id != 1) {
                for (int j = 1; j < id; ++j)
                    if (a[j] >= a[id]) {
                        int t = a[id];
                        for (int k = id; k > j; --k) 
                            a[k] = a[k - 1];
                        a[j] = t;
                        break;
                    }
            }
        }
        cout << bit << '\n';
    }
    return 0;
}

标签:959,const,int,cin,long,--,while,补题,Div
From: https://www.cnblogs.com/yhbqwq/p/18312872

相关文章

  • codeforce959
    CodeforcesRound959sponsoredbyNEAR(Div.1+Div.2)A.DiverseGametimelimitpertest:1secondmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputPetr,watchingSergey'sstream,cameupwithamatrix\(a\),c......
  • 7.18 史也分好坏,R959 是好史。
    CFR959(Div.1+2)Solve:A~E(5/8)Rank:777Rating:\(2117-1=2116\)发挥评价:Bad唉,天天喂这种比赛。然后我自己在简单题上唐完了,被卡住了,而且还被cf的波特验证控住了。以后少慌,加快速度,提前截好图。(其实最后已经会G了写完就上大分,但是来不及咯)争取下次上分吧。......
  • 杭电多校补题
    1001.循环位移#include<bits/stdc++.h>usingnamespacestd;typedefunsignedlonglongull;constintN=1048580*2;constintP=131;ullp[N],h1[N],h2[N];voidsolve(){stringa,b;cin>>a>>b;intn=a.size()......
  • 「比赛记录」CF Round 954 (Div. 3)
    CodeforcesRound954(Div.3)题目列表:A.XAxisB.MatrixStabilizationC.UpdateQueriesD.MathematicalProblemE.BeautifulArrayF.Non-academicProblemG1.PermutationProblem(SimpleVersion)G2.PermutationProblem(HardVersion)A.XAxis题......
  • Codeforces Round 959 sponsored by NEAR (Div. 1 + Div. 2)
    A直接速通就好了,我第一眼看的时候以为是整个数组可以有重复的数字,后面发现是保证没有的,所以直接随便交换一下位置就结束了。B,很经典的CF题,随便推导一下就能够发现,如果我想要一个位置能够发生变化,那么唯一的要求就是他以及他前面的位置有1出现过。而且完全不需要考虑为了一个数字......
  • Round 959
    A给定\(n*m\)数组\(a\),$1\lea_i\len*m$并且两两不同,问是否存在数组\(b\),也使用这些元素,并且每个位置的值都与\(a\)不同。\(1*1\)数组特判,其他循环移位。B给定01串s和t,可以对s任意次执行以下操作:选择l,r,将l,r异或等长前缀,问s和t是否能相等对于s和t第一个不同的位置......
  • Educational Codeforces Round 139 (Rated for Div. 2)
    A.ExtremelyRound----------------------------------题解-------------------------------------因为数据范围只有1e6,我们只需要预处理出来1-1e6每个每个数包含多少个极圆整数就行了,然后t次查询就可以。这种预处理查询是面对多次询问时应该首先想到的。点击查看代码#incl......
  • 题解:CF1912D Divisibility Test
    又是一道水绿。刚刚小学毕业的数学idiot——我释怀地笑了。第一种很好判断,当$b^k$为$n$的倍数时,取基数为$b$的能被$n$整除的整数$c$的最后$k$位数显然能被$n$整除。第二种也不难,当$b^k\equiv1\pmodn$时,取以$b$为底数的能被$n$整除的整数$c$的$k$......
  • 2024夏令营提高1模考0718模拟赛(提高1)补题报告
    2024夏令营提高1模考0718模拟赛(提高1)补题报告$$0718模拟赛(提高1)\\补题报告\2024年7月18日\by\\\唐一潇$$一、做题情况第一题比赛$100/100$,赛后通过第二题比赛$0/100$,赛后通过第三题比赛$0/100$,赛后通过第四题比赛$0/100$,赛后通过比......
  • 牛客day1的补题和总结
    C和I是签到题,没什么好说的。从A开始。A读题读了我20分钟,我才把样例弄懂。。这题目比cf阴间一佰倍,主要也是这类题的题面就是麻烦,有时候中文的题面的也能让我写一半回去再读几遍。这个主要就是写太慢了。完全可以更快的,而且这个思路我觉得大部分其实是lhgg帮我出的,我自己的思路......