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 << '\n'; }
  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 << '\n';
    else {
        cout << 2;
        for(int i = 1; i < n; i++) cout << 3;
        cout << '\n';   
    }
}
 
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 << '\n'; }
  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] << " \n"[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 << '\n'; }
  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 << '\n';
}
 
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 << '\n'; }
  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] = '\0';
        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) << '\n';
        return;   
    }
    for(int i = l; i <= r; i++) t[i - l + 1] = s[i];
    t[r - l + 2] = '\0';
    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 << '\n';
}
 
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,1\leq i\leq 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_i\leq 0\);這一條件可以弱化為:對於所有位置,都有\(b_i\leq 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 << '\n'; }
  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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM