前言:好不容易这次会这么多的题(偷溜出来打的,今天学校训练来着(线上讲题),对不住了朱哥T_T) 可恶的是就1:40,再多20分钟E就AC了。

A:

链接:https://ac.nowcoder.com/acm/contest/78306/A 利用a中的值,相加即可。类似于桶?

    int n, m;
    cin >> n >> m;
    int a[N], b[N];
    for(int i = 1 ;i <= n; i++) cin >> a[i];
    int ans = 0;
    for(int i = 0; i < m; i++) {
        int x;
        cin >> x;
        ans += a[x];
    }
    cout << ans;

B:两种情况,一输一赢,胜者+3,败者+0.平,都加1

链接:https://ac.nowcoder.com/acm/contest/78306/B 来源:牛客网 如果平局,则获得的分数差值为0,如果不平局,分数差值为3.那么只要判断分数差值是否为3的倍数(0倍也是)即可

    int x, y;
    cin >> x >> y;
    int t = abs(x - y);
    if(t % 3 != 0) cout << "No\n";
    else cout << "Yes\n";

C:(题目有点绕,看了半天题目才理解)给一个正整数n,要找到一个 最小的正整数 使得每一位都与原来的数不同。如果位数小于原来的数,那么要补上前缀0,且满足上述条件。

https://ac.nowcoder.com/acm/contest/78306/C 来源:牛客网

所以直接无脑找0呗,如果原序列未出现0,那么只用最后一位(个位)与原序列不同。注意0不是正数。

如果出现0,那要满足最小,就得把0改成1,然后非0改成0即可

    string s, tmp;
    cin >> s;
    int jud = 0;
    if(s.find('0') != string::npos) {
        int t = s.find('0');
        for(int i = t; i < s.size(); i++) {
            if(s[i] == '0') tmp += "1";
            else tmp += "0";
        }
        cout << tmp;
    }
    else {
        s[s.size() - 1] == '1' ? cout << 2 : cout << 1; 
        //没找到0时,最后一位是1,必须输出2***
    }

D:给m个区间,要求任意选取的区间(选或不选是两种),至少将n覆盖2次

链接:https://ac.nowcoder.com/acm/contest/78306/D 来源:牛客网

选或不选,利用递归枚举所有情况即可,每次递归到最后一层,进行差分即可。时间复杂度2^m + n

这边利用结构体进行存储左值和右值,利用bool数组进行枚举是否选择的情况。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int MOD = 998244353;
int n, m;
int sum = 0;
bool vis[20];
struct item {
    int l;
    int r;
}a[N];
void dfs(int x) {
    if(x == m) {
        int ans[N] = {0};
        for(int i = 0; i < m; i++) {
            if(vis[i] == true) {
                ans[a[i].l] += 1;
                ans[a[i].r + 1] -= 1; 
            }
        }
        for(int i = 1; i <= n; i++) {
            ans[i] = ans[i] + ans[i - 1];
            if(ans[i] < 2) return;
        }
        sum = (sum + 1) % MOD;
        return;
    }
    vis[x] = false;
    dfs(x + 1);
    vis[x] = true;
    dfs(x + 1);
}
void solve() {
    cin >> n >> m;
    for(int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;
        if(x > y) swap(x, y);
        a[i] = {x, y};
    }
    dfs(0);
    cout << sum;
}
int main() {
    int T = 1;
    // cin >> T;
    while(T--) {
        solve();
    }
}

E 给出有序的a任务和b任务,要求是做了前一个a,才能做后一个a任务。而b任务可做可不做,但必须上面的a做了b才能做。q(10)次询问,长度为1e5,需要nlogn做法

链接:https://ac.nowcoder.com/acm/contest/78306/E 来源:牛客网

(感觉比D简单,如果你没学过差分的话)

思路:a必须一个一个做,而b可以选择性的做,那只需要暴力将每次的b进行排序即可,取第k小的和。于是转化到了一个经典问题:第k小数。优先队列维护第K小数即可

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
using i64 = int64_t;
i64 a[N], b[N];
void solve() {
    i64 n, q;
    cin >> n >> q;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) cin >> b[i];
    for(int i = 0; i < q; i++) {
        int x;
        cin >> x;
        priority_queue<int> pq;
        i64 sum = 0;
        i64 ans = INT_MAX;
        for(int j = 1; j <= n; j++) {
            if(pq.size() != x) {
                pq.push(b[j]);
                sum += b[j] + a[j];
                ans = sum;
            } 
            else {
                sum += a[j];
                if(b[j] < pq.top()) {
                    sum -= pq.top();
                    sum += b[j];
                    pq.pop();
                    pq.push(b[j]);
                }
                ans = min(ans, sum);
            }
        }
        cout << ans << '\n';
    }
}

int main() {
    int T = 1;
    while(T--) {
        solve();
    }
}