首页 > 其他分享 >Codeforces Round 933 (Div. 3) A - G 题解

Codeforces Round 933 (Div. 3) A - G 题解

时间:2024-03-14 13:55:42浏览次数:32  
标签:int 题解 cin mx1 ++ vector solve 933 Div

Codeforces Round 933 (Div. 3)

A - Rudolf and the Ticket

Solution

因为 \(n\) 很小,直接枚举 \(b_i+c_j\) 所产生的所有数字

Code

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

void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    int ans = 0;
    vector<int> a(n), b(m);
    for (auto &x : a) cin >> x;
    for (auto &x : b) cin >> x;
    for (int i = 0; i < n; i++) 
        for (int j = 0; j < m; j++) 
            ans += a[i] + b[j] <= k;
    cout << ans << '\n';
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

B - Rudolf and 121

Question

给出 \(n\) 个数,可以进行这样一个操作,选中一个 \((1\le i \le n-1)\)

  • \(a_{i-1}=a_{i-1}-1\)
  • \(a_i=a_i-2\)
  • \(a_{i+1}=a_{i+1}-1\)

问能否把这 \(n\) 个数都变成 \(0\)

Solution

显然,\(a_1\) 只能每次 \(-1\) ,那么 \(a_2\) 就需要减 \(a_1\times 2\),\(a_3\) 需要减 \(a_1\)

从 \(1\) 开始往后枚举 \(i\),如果 \(a_i\) 还有剩余,就把 \(a_i\) 每次 \(-1\),然后计算 \(a_{i+1},a_{i+2}\) 当某个数出现负数的情况就是不合法的

Code

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

void solve() {
    int n; cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n - 2; i++) {
        if (a[i] > a[i + 1]) {
            puts("NO"); return ;
        }
        int x = a[i];
        if (a[i + 1] < x * 2) {
            puts("NO"); return ;
        }
        if (a[i + 2] < x) {
            puts("NO"); return ;
        }
        a[i] -= x; a[i + 1] -= x * 2; a[i + 2] -= x;
    }
    if (a[n - 1] != 0 || a[n] != 0) {
        puts("NO"); return ;
    }
    puts("YES");
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

C - Rudolf and the Ugly String

Question

一个串如果包含 \(pie\),\(map\) 就认为这个串是不美丽的

给出一个串,问最少删除几个字母使得串变美丽

Solution

显然,一个串如果出现 \(pie\) 只需要删除中间的 \(i\) 就可以打破 \(pie\)

同理 \(map\) 需要删去中间的 \(a\)

特殊地, \(mapie\) 需要删除中间的 \(p\),而不是删除 \(a\) 和 \(i\)

所以总次数就是 \(map\) 的个数 \(+\) \(pie\) 的个数 \(-\) \(mapie\) 的个数

Code

#include <bits/stdc++.h>
using namespace std;
void solve() {
    int n; cin >> n;
    string s; cin >> s;
    vector<string> p = {"pie", "map","mapie"};
    vector<int> num(3,0);
    for (int i = 0; i < 3; i++) {
        string now = p[i];
        for (int j = 0; j + now.size() - 1 < s.size(); j++) {
            if (s.substr(j, now.size()) == now)
                num[i] ++;
        }
    }
    cout << num[0] + num[1] - num[2] << '\n';
}
int main() {
    int t; cin >> t;
    while (t--) solve();
}

D - Rudolf and the Ball Game

Solution

DP 的思想,定义 \(dp[i][j]\) 表示前 \(i\) 次传球,\(j\) 位置是否有可能接球

顺时针传球认为是 \(j\Rightarrow j+x\) ,逆时针传球被认为是 \(j\Rightarrow j+n-x\)

Code

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

const int maxn = 1e3 + 5;

int f[maxn][maxn];

void solve(){
    int n, m, k; cin >> n >> m >> k;
    for (int i = 0; i < n; i++) {
        f[0][i] = i == k - 1;
    }
    for (int i = 1; i <= m; i++) {
        int x; char ch;
        cin >> x >> ch;
        for (int j = 0; j < n; j++) f[i][j] = 0;
        for (int j = 0; j < n; j++) {
            if (ch != '1') 
                f[i][(j + x) % n] |= f[i - 1][j];
            if (ch != '0') 
                f[i][(j + n - x) % n] |= f[i - 1][j];
        }
    }
    int ans = 0;
    for (int j = 0; j < n; j++) 
        if (f[m][j]) ans++;
    cout << ans << '\n';
    for (int j = 0; j < n; j++) 
        if (f[m][j]) cout << j + 1 << ' ';
    cout << '\n';
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

E - Rudolf and Imbalance

Solution

每一行单独看,定义 \(dp[i]\) 表示建桥建到 \(i\) 且必须在 \(i\) 建一个桥墩的最小代价,转移方程为 \(dp[i]=\min_{j=i-k-1}^{i-1}\{dp[j]+a[i]+1\}\)

单调队列优化转移过程即可

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;

int calc (vector<int> a, int d) {
    int n = a.size() - 1;
    vector<int> f(n + 1, 0);
    deque<pii> q;
    q.push_back({1, a[1] + 1}); f[1] = a[1] + 1;
    for (int i = 2; i <= n; i++) {
        while (q.size() > 0 && q.front().first < i - d) q.pop_front();
        f[i] = q.front().second + a[i] + 1;
        while (q.size() > 0 && q.back().second >= f[i]) q.pop_back();
        q.push_back({i, f[i]});
    }
    return f[n];
}

void solve() {
    int n, m, k, d; cin >> n >> m >> k >> d;
    d = d + 1;
    vector<vector<int> > a(n + 1, vector<int>(m + 1, 0));
    for (int i = 1; i <= n; i++) 
        for (int j = 1; j <= m; j++) 
            cin >> a[i][j];
    vector<int> p(n + 1);
    for (int i = 1; i <= n; i++) 
        p[i] = calc(a[i], d);
    vector<int> s(n + 1, 0);
    for (int i = 1; i <= n; i++) 
        s[i] = s[i - 1] + p[i];
    int ans = 1e18;
    for (int i = k; i <= n; i++) {
        ans = min(ans, s[i] - s[i - k]);
    }
    cout << ans << '\n';
    
}

signed main() {
    int t; cin >> t;
    while (t--) solve();
}

F - Rudolf and Imbalance

Solution

定义 \(mx1,mx2\) 分别表示差值的最大值和次大值

如果 \(mx1=mx2\) ,则无论怎么样都无法减小差值,直接输出 \(mx1\)

如果 \(mx1>mx2\) ,那么我们尝试在 \(mx1\) 之中插入一个数

假设 \(mx1\) 对应的位置是 \(pos\),那么我们就需要从 \(d,f\) 中找出一个组合,使得 \(d_i+f_j\) 距离 \((a[pos]+a[pos+1])/2\) 最近

这个暴力枚举 \(d_i\) ,二分查找 \(f_j\) 的值,统计答案即可

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int INF = 1e18;
void solve() {
    int n, m, k; cin >> n >> m >> k;
    vector<int> a(n + 1), d(m + 1), f(k + 1, 0);
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= m; i++) cin >> d[i];
    for (int i = 1; i <= k; i++) cin >> f[i];
    pii mx1 = {-1,0}, mx2 = {-1,0};
    for (int i = 1; i < n; i++) {
        int x = a[i + 1] - a[i];
        if (x > mx1.first) { mx2 = mx1; mx1 = {x, i}; }
        else if (x > mx2.first) { mx2 = {x, i}; }
    }
    if (mx1.first == mx2.first) {
        cout << mx1.first << '\n';
        return ;
    }
    // 把 pos1 的位置拆开
    int mid = (a[mx1.second] + a[mx1.second + 1]) / 2;
    sort (d.begin() + 1, d.end());
    sort (f.begin() + 1, f.end());
    int ret = mx1.first;
    for (int i = 1; i <= m; i++) {

        auto check = [&](int pos) {
            if (pos < 1 || pos > k) return INF;
            int x = d[i] + f[pos];
            if (!(x > a[mx1.second] && x < a[mx1.second + 1])) return INF;
            return max (x - a[mx1.second], a[mx1.second + 1] - x);
        };

        int pos = lower_bound(f.begin() + 1, f.end(), mid - d[i]) - f.begin();
        ret = min (ret, check(pos));
        ret = min (ret, check(pos - 1));
        ret = min (ret, check(pos + 1));
    }
    cout << max (mx2.first, ret) << '\n';
}

signed main() {
    int t; cin >> t;
    while (t--) solve();
}

G - Rudolf and Subway

Solution

把每个颜色分别建一个虚点,\(w\) 对应的虚点为 \(mp[w]\)

我们利用虚点对节点进行转移

如果存在一条 \(u,v\) 的边,颜色为 \(w\),需要用虚点进行过度

从 \(u\rightarrow mp[w]\),边权为 \(1\),从 \(v\rightarrow mp[w]\) ,边权为 \(1\)

从 \(mp[w]\rightarrow u\),边权为 \(0\),从 \(mp[w]\rightarrow v\),边权为 \(0\)

由于边权只有 \(01\) ,直接刷 \(01BFS\) 即可

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
void solve() {
    int n, m; cin >> n >> m;
    int cnt = n;
    map<int,int> mp;
    vector<vector<pair<int,int>>> g(n + m + 1);
    for (int i = 1; i <= m; i++){
        int u,v,w; cin >> u >> v >> w;
        if (mp.count(w) == 0) mp[w] = ++cnt;
        g[u].push_back({mp[w],1});
        g[v].push_back({mp[w],1});
        g[mp[w]].push_back({u,0});
        g[mp[w]].push_back({v,0});
    }
    int s, t; cin >> s >> t;
    vector<long long> dis(n + m + 1,INF);
    deque<int> q;
    dis[s] = 0; q.push_front(s);
    while (q.size()) {
        int u = q.front(); q.pop_front();
        for (auto &[v,w] : g[u]) {
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                if (w == 1) q.push_back(v);
                else q.push_front(v);
            }
        }
    }
    cout << dis[t] << '\n';
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

标签:int,题解,cin,mx1,++,vector,solve,933,Div
From: https://www.cnblogs.com/martian148/p/18072699

相关文章

  • thinkphp 5 跨域问题解决
    版本:5.1.41LTS从网上搜到好多从/public/index.php添加heade信息,或者用中间件,或者添加behavior操作,可以做到解决跨域问题,但是亲身试验了都不行,今天刚找了一个,可以使用,放在这里header('Access-Control-Allow-Credentials:true');header('Access-Control-Allow-Methods:GET,......
  • 常见问题解决 --- vmware地址分配失败
    vmware是根据分配给客户机的ip决定它处于什么网路。这句话非常抽象,我举例说明,vmware默认有三张网卡,一个桥接网卡,一个nat网卡,一个仅主机。我先说第一中情况 如果里配置客户机是桥接网卡,且在配置器中选择自动桥接。如果里宿主机有一张网卡,那么就桥接那一张网卡。并获取网路内的d......
  • Edu 12 --- Simple Subset -- 题解 (一个比较巧妙的思维算法题)
    SimpleSubset:题解:  思路解析:    题目要求任意两个数的和为质数,那我们最坏情况就是任意选择一个数,此时子集为最大。    如果子集中有两个奇数或者偶数,他们两个之和一定会被2整除,那么我们只能选择一奇一偶。    如果多个奇数都为1的话,他们两两......
  • 【NOIP2013模拟联考8】匹配(match) 题解
    B组都说看不懂……我也解释不清啊……只能写这么详细了ac自动机ac自动机上dp怎么才能判定一个母串是否包含几个模式串?我们可以想到ac自动机,考虑对模式串建ac自动机,如果我们跑到了一个标记为tail的节点,说明我们的母串包含了这一个模式串。所以我们设\(f[i][s][......
  • LeetCode[题解] 2864. 最大二进制奇数
    题目给你一个二进制字符串s,其中至少包含一个'1'。你必须按某种方式重新排列字符串中的位,使得到的二进制数字是可以由该组合生成的最大二进制奇数。以字符串形式,表示并返回可以由给定组合生成的最大二进制奇数。注意返回的结果字符串可以含前导零。示例1:输入:s......
  • 2024.03.13 题解
    CF566A.MatchingNames注意到要求公共前缀,所以先对所有字符串建出Trie树,则公共前缀长度等价于Trie树上两节点最近公共祖先的深度。设\(dfn_u\)表示u点的dfs序,\(dep_u\)表示u的深度,\(lca_{u,v}\)表示\(u\)和\(v\)的最近公共祖先。则对于\(dfn_a<dfn_b<d......
  • 洛谷 P2730 魔板 题解 DFS(广度优先搜索)
    题目背景在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有 8 个大小相同的格子的魔板:12348765题目描述我们知道魔板的每一个方格都有一种颜色。这 8 种颜色用前 8 个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左......
  • 每日"两"题 题解
    每日“二”题十年OI一场空,不开longlong见祖宗目录每日“二”题ABA题解:最值问题,一个条件在变,考虑使用二分:我们每次查找一个可切的最大巧克力,二分判断能不能这么切即可。C++代码voidsolve(){intn,k,l=1,r=0,ans;cin>>n>>k;vector<pair<int......
  • AT_abc343_g [ABC343G] Compress Strings 题解
    题目传送门前置知识前缀函数与KMP算法|状压DP解法由于\(\sum\limits_{i=1}^{n}|S_{i}|\)极大且不需要记录路径,所以luoguP2322[HNOI2006]最短母串问题的枚举所有可能的字符串\(T\)进行判断不可做。设\(f_{i,j}\)表示当“字符串包含状态”对应的二进制数为\(......
  • abc134F题解
    abc134F题意:定义长度为\(n\)的排列的怪异值为\(\sum_{i=1}^{n}\midp_i-i\mid\),问长度为\(n\),怪异值为\(k\)的排列数。思路:非常妙的dp题。\(\midp_i-i\mid\)可以看成上下两层数,将上层中的\(i\)和下层中的\(j\)匹配,怪异值增加\(i\),\(j\)中较大值减较小值。整体思路为从小到......