Codeforces Round #598 (Div. 3)


傳送門

A. Payment Without Change

簽到。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2019/11/4 21:19:19
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#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...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
int a, b, n, S;
 
void run(){
    cin >> a >> b >> n >> S;
    ll r = S - 1ll * a * n;
    if(r <= 0) r = S % n;
    if((ll)b >= r) pt("YES");
    else pt("NO");
}
 
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. Minimize the Permutation

題意:
給出一個\(1\)~\(n\)的排列,現在對於一個位置\(i\),可以交換\(a_i,a_{i+1}\)。但要滿足每個位置只能交換一次且最多交換\(n-1\)次。
輸出操作過后字典序最小的序列。

思路:
直接從后往前每個位置不斷貪心考慮即可。
每次掃一遍序列至少會交換一次,所以復雜度為\(O(n^2)\)

Code
/*
 * Author:  heyuhhh
 * Created Time:  2019/11/4 21:26:23
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#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...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 105;
 
int n;
int a[N];
bool chk[N];
 
void run(){
    cin >> n;
    int p;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    memset(chk, 0, sizeof(chk));
    int cnt = 0;
    while(1) {
        cnt = 0;
        for(int i = n - 1; i >= 1; i--) {
            if(chk[i]) continue;
            if(a[i + 1] < a[i]) {
                swap(a[i + 1], a[i]), ++cnt;
                chk[i] = 1;
            }
        }
        if(!cnt) break;
    }
    for(int i = 1; i <= n; i++) cout << a[i] << " \n"[i == 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;
}

C. Platforms Jumping

題意:
一個人位於\(0\)號位置,現在要跳到\(n+1\)號位置,每次跳躍能從\(x\)跳躍到\(x+1\)~\(x+d\)
給出\(m\)塊木板的長度,現在要你安排這\(m\)塊木板的位置(不改變相對順序,並且不能重疊),輸出最后的方案,或者這個人不能成功到\(n+1\)點。

思路:

  • 判斷可行性直接貪心判斷,此時在理想情況下,看這個人最遠能跳多遠;
  • 考慮具體方案時,設木板總長度為\(L\),那么就有\(n-L\)個空隙,這個空隙不能太長,也不能太短。
  • 因此直接根據這個空隙貪心來放木板即可。

詳見代碼:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2019/11/4 22:07:56
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#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...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1005;
 
int n, m, d;
int c[N];
int a[N], ans[N];
 
void run(){
    cin >> n >> m >> d;
    int tot = 0;
    for(int i = 1; i <= m; i++) cin >> c[i], tot += c[i];
    int s = 0;
    for(int i = 1; i <= m; i++) {
        s += d + c[i] - 1;
    }
    s += d;
    if(s < n + 1) {
        cout << "NO" << '\n';
        return ;
    }
    pt("YES");
    int r = n - tot;
    s = 0;
    for(int i = 1; i <= m; i++) {
        int t = min(r , d - 1);
        r -= t;
        s += t + 1;
        a[s] = i;
        s += c[i] - 1;
    }
    for(int i = 1, j; i <= n; i = j + 1) {
        j = i;
        if(a[i]) {
            for(; j <= i + c[a[i]] - 1; j++) ans[j] = a[i];
            --j;
        }
    }
    for(int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
	return 0;
}

D. Binary String Minimizing

題意:
給出一個\(01\)串,現在執行一次操作為:交換兩個相連位置的字符。
最多執行\(k\)次操作,輸出最終得到的字典序最小串。

思路:
每個\(0\)依次貪心往前移就行,按照前面\(1\)的個數來輸出方案。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2019/11/4 21:43:49
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#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...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
 
int n;
ll k;
char s[N];
int sum[N], has[N];
 
void run(){
    cin >> n >> k;
    cin >> (s + 1);
    int tot = 0;
    for(int i = 0; i <= n; i++) has[i] = 0;
    for(int i = 1; i <= n; i++) {
        sum[i] = sum[i - 1];
        if(s[i] == '1') ++sum[i], ++tot;
        else {
            ++has[sum[i]];
        }
    }
    for(int i = 1; i <= n && k; i++) if(s[i] == '0') {
        if((ll)sum[i] <= k) {
            --has[sum[i]];
            ++has[0];
            k -= sum[i];
        }   
        else {
            --has[sum[i]];
            sum[i] -= k;
            ++has[sum[i]];
            k = 0;
        }
    }
    int cnt = 0;
    while(cnt < tot) {
        while(has[cnt]--) cout << 0;
        cout << 1;
        ++cnt;
    }
    while(has[cnt]--) cout << 0;
    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. Yet Another Division Into Teams

題意:
\(n\)個學生分組,每組的“值”為最大值減去最小值。
現在要求每個組至少三個同學,問最后所有組的“值”的和的最小值為多少。

思路:

  • 顯然學生順序不影響答案,那么可以排個序。
  • 之后就是一個簡單的分組\(dp:dp[i]\)表示將前\(i\)個人進行分組的最小答案。轉移時枚舉前面的\(j\)進行轉移。
  • \(O(n^2)\)顯然不能承受,發現前面的\(dp\)值肯定選擇最小的,所以用優先隊列維護一下即可。

注意一些細節,詳細見代碼:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2019/11/5 9:03:50
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#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...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e5 + 5;
 
int n;
struct node{
    ll v;
    int id;
    bool operator < (const node &A) const{
        return v > A.v;
    }
}a[N];
 
ll dp[N];
int ans[N], tmp[N], from[N];
 
 
void run(){
    memset(from, 0, sizeof(from));
    memset(tmp, 0, sizeof(tmp));
    for(int i = 1; i <= n; i++) {
        cin >> a[i].v; a[i].id = i;
    }
    a[n + 1] = node{0, 0};
    sort(a + 1, a + n + 1, [&](node A, node B) {
        return A.v < B.v;
    });
    priority_queue <node> q;
    dp[0] = -a[1].v;
    q.push(node{dp[0], 0});
    for(int i = 1; i <= n; i++) {
        vector <node> vec(4);
        while(!q.empty()) {
            node now = q.top(); q.pop();
            vec.push_back(now);
            if(i - now.id >= 3) {
                dp[i] = now.v + a[i].v - a[i + 1].v;
                q.push(node{dp[i], i});
                from[i] = now.id;
                break;
            } 
        }
        for(auto it : vec) q.push(it);
    }
    int p = n;
    while(p) {
        tmp[from[p] + 1] = 1;
        p = from[p];        
    }
    for(int i = 1; i <= n; i++) tmp[i] += tmp[i - 1];
    cout << dp[n] << ' ' << tmp[n] << '\n';
    for(int i = 1; i <= n; i++) ans[a[i].id] = tmp[i];
    for(int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    while(cin >> n) run();
	return 0;
}

F. Equalizing Two Strings

題意:
給出兩個字符串,現在可以對兩個串任意多次同時翻轉長度相同的子串,詢問最終能否變為同一子串。

思路:

  • 因為可以任意多次翻轉,那么對於任意一次翻轉,我們可以等價於多個\(swap\)操作。之后我們就只考慮長度為\(2\)的翻轉操作。
  • 首先排除掉某種字符在兩個串中個數不相同的情況。
  • 可以發現:若\(t\)串中有兩個連續且相同的字符,那么一定合法。因為不斷交換這兩個不改變串模樣。
  • 進一步的推論:若\(t\)串中某個字符出現超過\(1\)次,就合法。
  • 接下來就只考慮長度不超過\(26\)的情況。現在判斷\(s\)串能否移動到\(t\)串,我們只需要看兩者逆序對個數的差值的奇偶性即可,如果為偶數則合法,否則不合法。

正確性腦補一下應該比較好理解...

Code
/*
 * Author:  heyuhhh
 * Created Time:  2019/11/4 22:38:32
 */
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#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...); }
#else
  #define dbg(...)
#endif 
void pt() {std::cout << '\n'; } template<typename T, typename...Args>
  void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); } using
  namespace std; typedef long long ll; typedef pair<int, int> pii;
//head
const int N = 2e5 + 5;
 
int n; char s[N], t[N];
int cnt[2][26];
int c1[N], c2[N];
 
void run(){
    cin >> n;
    cin >> (s + 1) >> (t + 1);
    for(int i = 0; i < 26; i++) {
        cnt[0][i] = cnt[1][i] = 0;
    }
    for(int i = 1; i <= n; i++) ++cnt[0][s[i] - 'a'];
    for(int i = 1; i <= n; i++) ++cnt[1][t[i] - 'a'];
    for(int i = 0; i < 26; i++) if(cnt[0][i] != cnt[1][i]) {
        pt("NO"); return; 
    }
    for(int i = 0; i < 26; i++) if(cnt[1][i] > 1) {
        pt("YES"); return;
    }
    int d = 0;
    for(int i = 1; i <= n; i++) 
        for(int j = i + 1; j <= n; j++) {
            if(s[j] - '0' < s[i] - '0') ++d;
            if(t[j] - '0' < t[i] - '0') --d;
        }
    if(d & 1) pt("NO");
    else pt("YES");
}
 
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;
}


免責聲明!

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



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