• Codeforces Global Round 7


    传送门

    A. Bad Ugly Numbers

    233333。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/3/19 22:36:37
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    void run() {
        int n; cin >> n;
        if(n == 1) cout << -1 << '
    ';
        else {
            cout << 2;
            for(int i = 1; i < n; i++) cout << 3;
            cout << '
    ';   
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    B. Maximums

    从前往后依次搞即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/3/19 22:39:26
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5;
     
    int n;
    ll a[N], b[N];
     
    void run() {
        ll Max = 0;
        cin >> n;
        for(int i = 1; i <= n; i++) cin >> b[i];
        for(int i = 1; i <= n; i++) {
            a[i] = b[i] + Max;
            Max = max(Max, a[i]);   
            cout << a[i] << " 
    "[i == n];
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    C. Permutation Partitions

    乘法原理运用。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/3/19 22:44:51
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5, MOD = 998244353;
     
    int n, k;
    pii a[N];
     
    void run() {
        cin >> n >> k;
        for(int i = 1; i <= n; i++) cin >> a[i].fi, a[i].se = i;
        sort(a + 1, a + n + 1);
        ll ans = 0;
        vector <int> pos;
        for(int i = n - k + 1; i <= n; i++) ans += a[i].fi, pos.push_back(a[i].se);
        sort(all(pos));
        int ans2 = 1;
        for(int i = 1; i < sz(pos); i++) {
            ans2 = 1ll * ans2 * (pos[i] - pos[i - 1]) % MOD;
        }
        cout << ans << ' ' << ans2 << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    D2. Prefix-Suffix Palindrome (Hard version)

    题意:
    给出一个字符串(s)
    现在要找到一个最长的串(t),满足:

    • (t)为一个回文串;
    • (t=pre_s+suf_s),即是(s)串不重叠的前缀和后缀的拼接。

    思路:
    可以注意到若(s)串首尾字符相同,那么我们可以直接去除不影响答案。
    简要证明:

    • 如果最后会去除一段前缀和一段后缀,那么我们一开始去掉不会影响答案,这种情况不用考虑。
    • 此时我们只会去除一段前缀/后缀。我们假设首位都去除了(x)个字符,现在(s')串首尾不相等,即我们此时不可能从(s')中选取前缀/后缀来形成回文串。不妨我们现在找到一个长度最大的前缀/后缀,其长度为(len),那么答案为(len+x);若不去除首尾(x)个字符,最大长度也为(len+x)

    那么直接贪心去掉前后相等的字符即可。
    现在我们只需要找到长度最大的前缀/后缀为回文串就行。
    可以马拉车或者回文自动机来搞,时间复杂度(O(n))
    马拉车代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/3/19 23:11:34
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    //#define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
     
    char s[N], t[N];
     
    struct Manacher{
        char ch[N << 1];
        int p[N << 1];
        void work(char *s) {
            int l = 0;
            ch[l++] = '&'; ch[l++] = '#';
            for(int i = 0; s[i]; i++) {
                ch[l++] = s[i];
                ch[l++] = '#';
            }
            ch[l] = '';
            int mx = 0, id = 0;
            for(int i = 0; i < l; i++) {
                p[i] = i < mx ? min(p[2 * id - i], mx - i) : 1;
                while(ch[i + p[i]] == ch[i - p[i]]) p[i]++;
                if(i + p[i] > mx) mx = i + p[i], id = i;
            }
        }
        bool chk(int l, int r) {
            int mid = (l * 2 + r * 2) >> 1;
            return p[mid] - 1 >= r - l + 1;
        }
    }Man;
     
    void run() {
        cin >> (s + 1);
        int n = strlen(s + 1);
        int l = 1, r = n;
        while(l <= r && s[l] == s[r]) ++l, --r;
        if(l > r) {
            cout << (s + 1) << '
    ';
            return;   
        }
        for(int i = l; i <= r; i++) t[i - l + 1] = s[i];
        t[r - l + 2] = '';
        Man.work(t + 1);
        int res = 0;
        pii seg;
        dbg(t + 1, Man.chk(1, 3));
        for(int i = l; i <= r; i++) {
            if(Man.chk(1, i - l + 1)) {
                if(i - l + 1 > res) {
                    res = i - l + 1;
                    seg = MP(l, i);
                }           
            }
            if(Man.chk(i - l + 1, r - l + 1)) {
                if(r - i + 1 > res) {
                    res = r - i + 1;
                    seg = MP(i, r);
                }           
            }
        }
        for(int i = 1; i <= n; i++) {
            if(i < l || i > r || (i >= seg.fi && i <= seg.se)) {
                cout << s[i];
            }   
        }
        cout << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    E. Bombs

    题意:
    给出一个(1...n)的排列(p_i),给出一个序列(q_i),表示(q_i)位置上面的数会成为一个炸弹。
    现在定义排列的“工作”:

    • 依次添加(p_1,...,p_n)到空集(S)中;
    • 若当前(i)位置为一个炸弹,那么会从集合(S)中取出一个最大的数。

    现在回答对于每个(i,1leq ileq n,q_1,q_2,cdots,q_{i-1})都成为炸弹后,排列“工作”过后剩下的最大值是多少。

    思路:

    • 显然最后的答案具有单调不增性。
    • 考虑从大到小进行枚举答案,那么我们只需要(check)当前答案是否合法即可。
    • 假设当前答案为(x),那么满足当前答案不合法的充要条件为:假设当前不小于(x)的数的位置从小到大依次为(pos_1,cdots,pos_k),那么至少有(t)个炸弹位置不小于(pos_{k-t+1})
    • 那么我们维护一个(b_i),表示(i...n)这段后缀中,不小于(x)的数的个数减去这段中炸弹的个数。那么可以将上述充要条件修改为:对于所有大于等于(x)的位置,都有(b_ileq 0);这一条件可以弱化为:对于所有位置,都有(b_ileq 0)
    • 因为我们维护的是两个数的差,当答案减小或者插入炸弹时,都只会影响一个前缀或者后缀,所以利用线段树维护一下就行。

    挺有难度的一个题,如果想到了第三点那么之后应该就比较好想了,考场上就一直在思考有没有什么比较简单的方法来(check)。但其实第三点的思路就是很简单的贪心。
    貌似还有(O(n))的做法,知道了过后再来补(咕咕咕)

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/3/20 10:13:26
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 3e5 + 5;
     
    int n;
    int p[N], q[N], pos[N];
     
    int maxv[N << 2], lz[N << 2];
     
    void tag(int o, int l, int r, ll v) {
        maxv[o] += v;
        lz[o] += v;
    }
     
    void push_up(int o) {
        maxv[o] = max(maxv[o << 1], maxv[o << 1|1]);
    }
     
    void push_down(int o, int l, int r) {
        if(lz[o] != 0) {
            int mid = (l + r) >> 1;
            tag(o << 1, l, mid, lz[o]);
            tag(o << 1|1, mid + 1, r, lz[o]);
            lz[o] = 0;   
        }
    }
     
    void update(int o, int l, int r, int L, int R, ll v) {
        if(L <= l && r <= R) {
            tag(o, l, r, v);
            return;
        }   
        push_down(o, l, r);
        int mid = (l + r) >> 1;
        if(L <= mid) update(o << 1, l, mid, L, R, v);
        if(R > mid) update(o << 1|1, mid + 1, r, L, R, v);
        push_up(o);
    }
     
    void run() {
        cin >> n;
        for(int i = 1; i <= n; i++) cin >> p[i], pos[p[i]] = i;
        for(int i = 1; i <= n; i++) cin >> q[i];
        int k = n;
        cout << k << ' ';
        update(1, 1, n, 1, pos[k], 1);
        for(int i = 1; i < n; i++) {
            update(1, 1, n, 1, q[i], -1);
            while(1) {
                int Max = maxv[1];
                if(Max <= 0) {
                    update(1, 1, n, 1, pos[--k], 1);
                } else break;
            }
            cout << k << ' ';
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    预习原码补码
    C语言I作业12-学期总结
    C语言I博客作业11
    C语言I博客作业10
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言I作业004
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12530808.html
Copyright © 2020-2023  润新知