• Codeforces Global Round 13 A-D题题解


    写在前边

    链接:Codeforces Global Round 13
    (A,B,C,D)

    A. K-th Largest Value

    链接:A题链接

    题目大意:

    有一个字串只由(0、1)组成,有两个操作,(1)是让其中(a_x)变为(1-a_x)(2)是询问数组中第(k)大的数。

    思路

    很简单了,字串中元素只在(0、1)中变化,要问第(k)大的数字,那么非(1)(0),就用一个(map)维护(0,1)的数量就好了

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int Mod = 10000007;
    
    const int N = 1E5 + 10;
    int a[N];
    
    void solve() {
        int n, q;
        scanf("%d%d", &n, &q);
        map<int, int> cnt;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            cnt[a[i]]++;
        }
        while (q--) {
            int t, x;
            scanf("%d%d", &t, &x);
            if (t == 1) {
                if (a[x] == 1) {
                    a[x] = 0;
                    cnt[0]++, cnt[1]--;
                } else {
                    a[x] = 1;
                    cnt[1]++, cnt[0]--;
                }
            } else if (t == 2) {
                if (cnt[1] >= x) puts("1");
                else puts("0");
            }
        }
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        solve();
        return 0;
    }
    

    B. Minimal Cost

    链接:B题链接

    题目大意:

    每行一个箱子,第(i)行箱子的坐标为(a_i),你的任务就是推箱子,然后把利用最小的花费把开一条路使得你可以从左上角走到右下角。

    思路

    注意

    1. 每行就一个!
    2. 你可以随便方向的走!
      那么这样就很简单了,只需要在一列箱子中开一个口就好了,然后不断更新答案即可。

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int Mod = 10000007;
    
    const int N = 110;
    int a[N];
    
    void solve() {
        int n, u, v;
        scanf("%d%d%d", &n, &u, &v);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        
        int res = 2e9 + 10;
        for (int i = 2; i <= n; i++) {
            if (abs(a[i] - a[i - 1]) > 1) res = 0;
            if (a[i] == a[i - 1]) res = min(res, v + min(v, u));
            if (abs(a[i] - a[i - 1]) == 1) res = min(res, min(v, u));
        }
    
        printf("%d
    ", res);
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        int t;
        scanf("%d", &t); 
        while (t--) {
            solve();
        }
    
        return 0;
    }
    

    C. Pekora and Trampoline

    链接:C题链接

    题目大意:

    跳床,有(n)个跳床,床的高度为(s_i),每在上边跳一次那么(s_i)减小(1),每次跨越着跳,当前在(i)那么一步会跳到(i + s_i)去,每次可以从任意一个跳床开始跳,直到跳出所有跳床算一次操作,那么经过多少次操作,所有的(s_i)都变为(1),注意已经变为(1)的床不会再减小。

    思路

    贪心的想,假如我们要是所有的床都变为(1),那么我们每次一定得从最左边跳到最右边,所以不如直接贪心加模拟的方法解题。

    1.维护一个(p)数组,(p_i)表示已经在第(i)张床上跳了(p_i)次。
    2.更新答案(res += max(0, s[i] - p[i] - 1)),即如果(s[i] - 1 > p[i])说明还需要在第i张床上跳(s[i] - p[i] - 1)次,如果(s[i] - 1 leq p[i]),那么说明第(i)张床上(s[i])已经变为(1)。同时如果在第i张床上跳,因为(s[i])每次减一,直到减法为(1)((s[i] = 1)就没必要跳了),那么会影响后边第(i + s[i], ...,i + 2)床。
    3. 还有就是,如果第(i)张床上跳的过多,即(s[i])已经变为(1)了,那么第(i)张床上多余的跳跃次数可以转移到下一张床上。

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int Mod = 10000007;
    
    LL gcd(LL a, LL b) {
        return b ? gcd(b, a % b) : a;
    }
    
    const int N = 5010;
    int s[N];
    int p[N];
    
    void solve() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &s[i]);
    
        LL res = 0;
        memset(p, 0, sizeof p);
        for (int i = 1; i <= n; i++) {
            int x = max(0, s[i] - p[i] - 1); 
            res += x;
            for (int j = i + 2; j <= min(n, i + s[i]); j++) {
                p[j]++;
            }
            p[i + 1] += max(p[i] - s[i] + 1, 0);
        }
        printf("%lld
    ", res);
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        int t;
        scanf("%d", &t); 
        while (t--) {
            solve();
        }
        return 0;
    } 
    

    D. Zookeeper and The Infinite Zoo

    链接:D题链接

    题目大意:

    可以在结点(u)(u+v)连一条边,当前仅当(u \, & \, v = v)的时候,然后给定(q)个询问,每次两个端点(u_i), (v_i)问是否能从(u_i)(v_i)

    思路

    首先发现两个性质:

    1. 假如现结点为(v),那么它一定可以转移到(2 * v),很显然。
    2. 还有就是要满足(u \, & \, v = v),那么起码满足(u leq v),否则直接(pass)掉即可

    然后再推到发现,(u)(1)的个数必须要大于等于(v)(1)的个数,为什么呢?
    我们令(k = v - u).
    我们发现,因为(u \, & \, k = k),那么说明,(u)(k)的二进制数中存在(1)的位数一定在同一位啊,否则不可能按位与得到(k),然后实现(u)转移到(u+k = v),那么(v)相对于(u)来说肯定是(u)其中的某些(1)进位才得到了(u+k = v),那么所以说(v)(1)得个数肯定是小于等于(u)(1)得个数的,举两个例子:
    (u_(2) = 011), (k_(2) = 001),那么(v_(2) = 100)(1)的个数减少了。
    (u_(2) = 011), (k_(2) = 011),那么(v_(2) = 110)(1)的个数不变。
    那么单纯满足这个条件就对了吗,当然不是。
    还要满足,(v)中的每一位(1)要高于(u)中每一位的(1),总不能越转移越低吧。那么满足这两个条件,(u)(v)就可以进行转移了,那么上边的操作都可以用(lowbit)运算就可以了

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    #define pub push_back
    #define pob pop_back
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int Mod = 10000007;
    
    int lowbit(int x) {
        return x & (-x);
    }
    
    void solve() {
        int u, v;
        scanf("%d%d", &u, &v);
        
        if (u > v) {
            puts("NO");
            return;
        }
        int uu = u, vv = v;
        int cnt1 = 0, cnt2 = 0;
        while (uu) { //u中1的个数
            uu -= lowbit(uu);
            cnt1++;
        }
        while (vv) { //v中1的个数
            vv -= lowbit(vv);
            cnt2++;
        }
        while (u && v) { //必须往高位推才行
            if (lowbit(u) > lowbit(v)) {
                puts("NO");
                return;
            }
            u -= lowbit(u), v -= lowbit(v); 
        }
        if (cnt1 >= cnt2) puts("YES");
        else puts("NO");
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        int t;
        scanf("%d", &t); 
        while (t--) {
            solve();
        }
    
        return 0;
    }
    
  • 相关阅读:
    linux 配置Apache 、PHP
    SQL Server DML(SELECT)常见用法(二)
    SQL Server DML(UPDATE、INSERT、DELETE)常见用法(一)
    PropertyGrid—添加EventTab
    PropertyGrid—添加属性Tab
    PropertyGrid—默认属性,默认事件,属性默认值
    PropertyGrid—为复杂属性提供下拉式编辑框和弹出式编辑框
    PropertyGrid--为复杂属性提供编辑功能
    PropertyGrid--基本功能
    Intellij IDEA使用(一)项目模板类型
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/14487739.html
Copyright © 2020-2023  润新知