• AcWing第12场周赛题解


    A. 3803. 数组去重

    题目链接:https://www.acwing.com/problem/content/3806/

    题目大意:给数组去重,相同数字输出最右边一个。

    解题思路:开一个 set 从右往左判断是否第一个出现,用 vis[] 数组标记是否要输出。

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    int T, n, a[55];
    bool vis[55];
    set<int> st;
    
    int main() {
        cin >> T;
        while (T--) {
            cin >> n;
            for (int i = 0; i < n; i++) cin >> a[i];
            memset(vis, 0, sizeof(vis));
            st.clear();
            for (int i = n-1; i >= 0; i--) {
                if (!st.count(a[i])) {
                    st.insert(a[i]);
                    vis[i] = true;
                }
            }
            cout << st.size() << endl;
            bool flag = false;  // 空格
            for (int i = 0; i < n; i++) {
                if (vis[i]) {
                    if (!flag) flag = true;
                    else cout << " ";
                    cout << a[i];
                }
            }
            cout << endl;
        }
        return 0;
    }
    

    B. 3804. 构造字符串

    题目链接:https://www.acwing.com/problem/content/3807/

    题目大意:构造一个长度为 \(k\) 的,和字符串 \(s\) 具有相同字符集的,字典序大于 \(s\) 的,字典序最小的字符串 \(t\)

    解题思路:

    r[1]r[m] 表示 s 中(ASCII码从小到大排)出现过的字符。
    如果 k > n,则在 s 后面补 k - nr[1]
    否则,从后往前找第一次出现的 s[i] < r[m] 的那个字符 s[i],将 s[i] 改为字符集中比它大的ASCII码最小的字符;同时将其后字符都修改为 r[1]

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 5;
    char s[maxn], t[maxn], r[33];
    int T, n, k, m;
    bool vis[33];
    
    int main() {
        cin >> T;
        while (T--) {
            cin >> n >> k >> s;
            memset(vis, 0, sizeof(vis));
            for (int i = 0; i < n; i++)
                vis[s[i] - 'a'] = true;
            m = 0;
            for (int i = 0; i < 26; i++)
                if (vis[i])
                    r[++m] = 'a' + i;
            if (k > n) {
                cout << s;
                for (int i = n; i < k; i++)
                    cout << r[1];
                cout << endl;
                continue;
            }
            s[k] = 0;
            for (int i = k-1; i >= 0; i--) {
                if (s[i] < r[m]) {
                    int p = upper_bound(r+1, r+1+m, s[i]) - r;
                    s[i] = r[p];
                    for (int j = i+1; j < k; j++)
                        s[j] = r[1];
                    break;
                }
            }
            cout << s << endl;
        }
        return 0;
    }
    

    C. 3805. 环形数组

    题目链接:https://www.acwing.com/problem/content/3808/

    题目大意:区间更新+区间最小值。

    解题思路:若 \(l \gt r\),则操作两个区间 \([l,n-1]\)\([0,r]\) 即可。

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 5;
    int n, m, o[3];
    long long tree[maxn<<2], lazy[maxn<<2];
    
    string s;
    
    void push_up(int rt) {
        tree[rt] = min(tree[rt<<1], tree[rt<<1|1]);
    }
    
    void push_down(int l, int r, int rt) {
        if (l < r && lazy[rt]) {
            lazy[rt<<1] += lazy[rt];
            lazy[rt<<1|1] += lazy[rt];
            tree[rt<<1] += lazy[rt];
            tree[rt<<1|1] += lazy[rt];
            lazy[rt] = 0;
        }
    }
    
    #define lson l, mid, rt<<1
    #define rson mid+1, r, rt<<1|1
    
    void build(int l, int r, int rt) {
        if (l == r) {
            cin >> tree[rt];
            return;
        }
        int mid = (l + r) / 2;
        build(lson);
        build(rson);
        push_up(rt);
    }
    
    void update(int L, int R, int d, int l, int r, int rt) {
        if (L <= l && r <= R) {
            tree[rt] += d;
            lazy[rt] += d;
            return;
        }
        push_down(l, r, rt);
        int mid = (l + r) / 2;
        if (L <= mid) update(L, R, d, lson);
        if (R > mid) update(L, R, d, rson);
        push_up(rt);
    }
    
    long long query(int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R) return tree[rt];
        push_down(l, r, rt);
        int mid = (l + r) / 2;
        long long res = (1LL<<60);
        if (L <= mid) res = min(res, query(L, R, lson));
        if (R > mid) res = min(res, query(L, R, rson));
        return res;
    }
    
    int main() {
        cin >> n;
        build(0, n-1, 1);
        cin >> m;
        getline(cin, s);    // 读取m后的一个空行
        while (m--) {
            getline(cin, s);
            stringstream ss(s);
            int x = 0;
            while (ss >> o[x]) x++;
            int l = o[0], r = o[1];
            if (x == 3) {
                int d = o[2];
                if (l <= r) update(l, r, d, 0, n-1, 1);
                else update(l, n-1, d, 0, n-1, 1), update(0, r, d, 0, n-1, 1);
            }
            else {
                long long ans;
                if (l <= r) ans = query(l, r, 0, n-1, 1);
                else ans = min(query(l, n-1, 0, n-1, 1), query(0, r, 0, n-1, 1));
                cout << ans << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【洛谷】P2880 [USACO07JAN]平衡的阵容Balanced Lineup(st表)
    【洛谷】P1052 过河(状压dp)
    【洛谷】P1541 乌龟棋(四维背包dp)
    【BZOJ】4721: [Noip2016]蚯蚓 / 【洛谷】P2827 蚯蚓(单调队列)
    【洛谷】P1064 金明的预算方案(dp)
    【洛谷】P3908 异或之和(异或)
    【洛谷】P2434 [SDOI2005]区间(暴力)
    【洛谷】P2694 接金币(排序)
    【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)
    【游记】noip2017酱油记
  • 原文地址:https://www.cnblogs.com/quanjun/p/16127441.html
Copyright © 2020-2023  润新知