Codeforces Round #650 (Div. 3)

传送门
视频题解

ABCgugugu...

D. Task On The Board

从大到小依次确定,暴力计算是否符合即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/16 23:14:00
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#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 << std::endl; }
  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, m;
    string s; cin >> s;
    n = s.length();
    vector <int> cnt(26);
    for (int i = 0; i < n; i++) {
        ++cnt[s[i] - 'a'];
    }
    cin >> m;
    vector <int> b(m);
    for (int i = 0; i < m; i++) {
        cin >> b[i];
    }
    vector <int> fixed(m);
    for (int i = 0; i < m; i++) {
        if (b[i] == 0) {
            fixed[i] = 1;
        }
    }
    int T = 1;
    while (count(all(fixed), 0)) {
        ++T;
        vector <int> will;
        for (int i = 0; i < m; i++) {
            if (!fixed[i]) {
                int t = 0;
                for (int j = 0; j < m; j++) {
                    if (fixed[j]) {
                        t += abs(i - j);
                    }
                }
                if (t == b[i]) {
                    will.push_back(i);
                }
            }
        }
        for (auto it : will) {
            fixed[it] = T;
        }
    }
    int p = 25;
    vector <char> ans(m);
    for (int t = 1; t <= T; t++) {
        int num = 0;
        for (int i = 0; i < m; i++) {
            if (fixed[i] == t) {
                ++num;
            }
        }
        while (p >= 0 && cnt[p] < num) --p;
        for (int i = 0; i < m; i++) {
            if (fixed[i] == t) {
                ans[i] = (p + 'a');
            }
        }
        --p;
    }
    for (auto it : ans) {
        cout << it;
    }
    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. Necklace Assembly

因为数据范围很小,直接枚举环长度。然后枚举\(k\)的所有因子\(d\),然后求出合法的放置字符的个数进行check即可。
详见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/16 22:41:13
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#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 << std::endl; }
  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, k; cin >> n >> k;
    vector <int> v;
    for (int i = 1; i <= k; i++) {
        if (k % i == 0) {
            v.push_back(i);
        }
    }
    string s; cin >> s;
    vector <int> cnt(26);
    for (int i = 0; i < n; i++) {
        ++cnt[s[i] - 'a'];
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (auto it : v) {
            if (it % i == 0) {
                ans = max(ans, i);
            }
            if(i % it == 0) { 
                int d = i / it;
                int c = 0;
                for (int j = 0; j < 26; j++) {
                    c += cnt[j] / d;
                }
                if (c >= it) {
                    ans = max(ans, i);
                }
            }
        }
    }
    cout << ans << '\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;
}

F1. Flying Sort (Easy Version)

题意:
给定长度为\(n,n\leq 2000\)的序列\(a\),保证序列中的数两两互不相同。
一次操作可以将序列中的任意一个数放在最前面或者最后面,问最少多少次操作能使得序列\(a\)非降。

思路:

  • 观察到操作可以由对一个字符操作变为对一个连续的单增子序列进行操作,操作代价为子序列长度。
  • 那么提取出若干个最长的连续单增子序列直接进行拼接即可。
  • 设最长的长度为\(max\),显然可以发现保持该序列不动,其余直接拼接即可,答案即为\(n-max\)

因为该题数据范围很小,直接暴力即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/16 23:38:50
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#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 << std::endl; }
  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;
    vector <int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(all(b));
    b.erase(unique(all(b)), b.end());
    for (int i = 0; i < n; i++) {
        a[i] = lower_bound(all(b), a[i]) - b.begin();
    }
    int p = 0, Max = 0;
    while (p < n) {
        int len = 0;
        for (int i = 0; i < n; i++) {
            if (a[i] == p) {
                ++len, ++p;
            }
        }
        Max = max(Max, len);
    }
    cout << n - Max << '\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;
}

F2. Flying Sort (Hard Version)

题意:
题意类似于\(F1\)
差别在于\(n\leq 10^5\),并且序列中可能会存在相同的数。

思路:

  • 借鉴\(F1\)的思路,我们找一个最长的连续非降序列来进行拼接。但因为此题可能会存在相同的字符,直接选取过后进行拼接可能会有问题。
  • 手玩数据可以发现,我们要找的子序列满足如下形式:\(A+B+C\)。大致分为三个部分,中间的数一定要求满足全部出现在子序列中,两端的数不一定要求全部出现,出现若干个即可。
  • 这样我们进行拼接一定存在至少一种方案使得序列非降。

所以找到这样的最长序列长度即可,其余直接拼接在首/尾就行,答案即为\(n-max\)
代码的话写得有点复杂,直接\(dp\)来表示状态,感觉会存在有更简单的方法:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/17 0:08:56
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#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 << std::endl; }
  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;
    vector <int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        b[i] = a[i];
    }
    sort(all(b));
    b.erase(unique(all(b)), b.end());
    for (int i = 0; i < n; i++) {
        a[i] = lower_bound(all(b), a[i]) - b.begin();
    }   
    vector <vector <int>> pos(n);
    for (int i = 0; i < n; i++) {
        pos[a[i]].push_back(i);
    }
    auto last = [&] (int v, int p) {
        int t = lower_bound(all(pos[v]), p) - pos[v].begin() - 1;
        if (t == -1) return t;
        return t;
    };
    vector <vector <int>> dp(n, vector <int>(2, 0));
    dp[0][0] = sz(pos[0]);
    int Max = sz(pos[0]);
    for (int i = 1; i < n; i++) if (sz(pos[i])) {
        int cnt = sz(pos[i]);
        int k = last(i - 1, pos[i][0]);
        if (k == -1) {
            dp[i][0] = cnt;
        } else {
            if (k == sz(pos[i - 1]) - 1) {
                dp[i][0] = dp[i - 1][0] + cnt;
                dp[i][1] = dp[i - 1][1] + cnt;
            } else {
                dp[i][1] = k + 1 + cnt;
            }
        }
        for (int j = 0; j < cnt; j++) {
            int p = pos[i][j];
            int k = last(i - 1, p);
            if (k == -1) {
                Max = max(Max, cnt - j);
            } else {
                if (k == sz(pos[i - 1]) - 1) {
                    Max = max(Max, max(dp[i - 1][0], dp[i - 1][1]) + cnt - j);
                } else {
                    Max = max(Max, cnt - j + k + 1);
                }
            }
        }
    }
    for (int i = 0; i < n; i++) {
        Max = max(Max, max(dp[i][0], dp[i][1]));
    }
    cout << n - Max << '\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;
}
posted @ 2020-06-17 14:52  heyuhhh  阅读(479)  评论(0编辑  收藏  举报