• 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 << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    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 << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    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] << " 
    "[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 << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    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" << '
    ';
            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] << " 
    "[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 << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    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 << '
    ';
    }  
     
    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 << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    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] << '
    ';
        for(int i = 1; i <= n; i++) ans[a[i].id] = tmp[i];
        for(int i = 1; i <= n; i++) cout << ans[i] << " 
    "[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 << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif 
    void pt() {std::cout << '
    '; } 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;
    }
    
  • 相关阅读:
    文件上传及文件大小限制_学习笔记
    Java后台及Jsp前端的简单分页_学习笔记
    Java过滤器Filter的原理及配置_学习笔记
    Jsp入门EL表达式_学习笔记
    关于forName()、newInstance()、getMethod()、getClass()等区别的简略说明
    SQL语句查询某字段不同数据的个数(DISTINCT 的使用)
    C# 中delegate和event的区别
    java面试题(转)
    Servlet中的几个重要的对象(转)
    Spring 注解注入的几种方式(转)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11797516.html
Copyright © 2020-2023  润新知