• Codeforces Round #700 (Div. 2) A B C D1


    比赛链接

    A - Yet Another String Game

    Problem 1480A - Yet Another String Game

    Alice和Bob在玩回合制游戏,Alice先手。每次操作可以使得给定字符串任意一个位置字符变成任意一个字符(小写字符),已修改过的位置不能再改,如果所有位置都被修改则游戏结束。Alice目的是使得最终字符串字典序尽可能小,Bob反之。

    Solution

    签到题,因为字典序要最小,所以每次修改的位置都尽可能的靠前,就变成了Alice和Bob依次修改。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 5e5 + 10;
    char ans[maxn];
    void solve()
    {
    
        scanf("%s", ans);
        int n = strlen(ans);
        for (int i = 0; i < n; ++ i)
        {
            if(i%2 == 0)
            {
                if(ans[i] == 'a')
                    ans[i] = 'b';
                else
                    ans[i] = 'a';
            }
            else
            {
                if(ans[i] == 'z')
                    ans[i] = 'y';
                else
                    ans[i] = 'z';
            }
        }
        printf("%s
    ", ans);
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while (t--)
        {
            solve();
        }
        return 0;
    }

    B - The Great Hero

    Problem 1480B - The Great Hero

    Hero的攻击力 A,血量 B。i-th monster 攻击力 ai,血量bi。Hero每次攻击一个monster双方都会损失对方攻击力等值血量。任何一个生命HP<=0时死亡。问Hero能否杀死所有的monster。即使在最后一击时同归于尽。

    Solution

    签到题。唔,当时做的时候是觉得攻击力最高的放最后打,后来看到了聚聚们的题解,发现全打一遍,然后依次判断每一只放到最后打是否可以获胜,比我场上的解法会更容易证明。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn = 1e5 + 10;
    char ans[maxn];
    struct Moster
    {
        ll a, b, daijia;
    } moster[maxn];
    bool cmp(Moster x, Moster y)
    {
        if(x.a == y.a)
            return x.b < y.b;
        return x.a < y.a;
    }
    void solve()
    {
        ll A, B, n;
        scanf("%lld %lld %lld", &A, &B, &n);
        for (int i = 1; i <= n; ++ i)
            scanf("%lld", &moster[i].a);
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%lld", &moster[i].b);
        }
    
        sort(moster + 1, moster + 1 + n, cmp);
    
        for (int i = 1; i <= n; ++ i)
        {
            ll t1 = (moster[i].b + A - 1) / A;
            ll t2 = (B + moster[i].a - 1) / moster[i].a;
            if(t2 > t1)
                B -= t1 * moster[i].a;
            else if(t1 == t2)
            {
                if(i == n)
                {
                    printf("YES
    ");
                    return;
                }
                printf("NO
    ");
                return;
            }
            else
            {
                printf("NO
    ");
                return;
            }
        }
    
        printf("YES
    ");
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while (t--)
        {
            solve();
        }
        return 0;
    }

    C. Searching Local Minimum

    Problem 1479A - Searching Local Minimum

    交互题。给定一个全排列,你一共可以进行不超过100次询问,每次询问可以询问一个下标并得到对应位置上的值。输出这个序列中任意一个局部最小数。局部最小数的定义为i-th的值比(i+1)-th的值和(i-1)-th的值都小。0-th和(n+1)-th上的值定义为+∞。

    Solution

    如果我们把值都二维坐标轴上,那么我们会得到若干条首尾相连的直线,那么我们的目的就是找到其中一个任意两条k1*k2<0且相连直线的交点(这样的点一定存在,因为数组两端值都为+∞)。那么我们每次去二分i-th和(i+1)-th上的值,如果前者小于后者那么在i-th左侧一定存在答案,反之在右侧。(画图易证)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    int a[maxn];
    int n;
    void ff()
    {
        fflush(stdout);
    }
    int ask(int x)
    {
        printf("? %d
    ",x);
        ff();
        int temp;
        scanf("%d", &temp);
        return temp;
    }
    void out(int x)
    {
        printf("! %d
    ",x);
        ff();
        exit(0);
    }
    void check(int x)
    {
        if(a[x] == 0)
            a[x] = ask(x);
        if(a[x+1] == 0)
            a[x + 1] = ask(x + 1);
        if(a[x-1] == 0)
            a[x - 1] = ask(x - 1);
        if (a[x] < a[x + 1] && a[x] < a[x - 1])
        {
            out(x);
        }
    }
    int main()
    {
        scanf("%d", &n);
        a[0] = a[n + 1] = n + 1;
        check(1);
        check(n);
        int l = 1, r = n - 1;
        int ans = 0;
        while (l <= r)
        {
            int mid = l + r >> 1;
            check(mid);
            if(a[mid]<a[mid+1])
                r = mid - 1;
            else
                l = mid + 1;
        }
    }

    D1 - Painting the Array I

    Problem 1479B1 - Painting the Array I

    给定一个序列a,需要分成a1,a2两个序列,每个数只能被分到一个序列中,且同意序列中的数相对位置不变。定义seg(a)为将序列中相邻值相等的数合并后序列剩下的数。求max(seg(a1)+seg(a2))

    Solution

    贪心。易得,我们只需要考虑两个序列最后一个数字即可。设 ll 为a0序列最后一个元素,rr 为a1序列最后一个元素。

    ll 和 rr 和当前值 i-th 有四种关系

    • 其中一个与 i-th相等,另一个不等,那么肯定将当前值移到不相等的序列最优
    • 两个数都与 i-th相等,那么随便移
    • 两个数都与 i-th不相等,那么就需要考虑 (i+1)-th这个数与 ll 和 rr 的关系了
    1. 如果 ll 与 (i+1)-th相等,那么就将当前的 i-th移到 ll 所在序列,这样就可能避免后面 (i+1)-th只能选择一个导致 (i+2)-th本能做出贡献但是无效的情况
    2. 反之亦然,如果都相等或者都不相等就无所谓了

    比如 ll = 1  rr = 3,i-th = 2,(i+1)-th = (i+2)-th = 3 。如果我们默认在都不相等的情况下都分配给 ll 的策略,会发现到 (i+2)-th位置上的3本可以做出贡献但是在这个策略下他面临两个3的境况。

    但我们知道,最优策略是 i-th分配给 rr,(i+1)-th随意分配,这样 (i+2)-th位置也可以产生贡献了。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    int n;
    int arr[maxn];
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%d", arr + i);
        }
    
        int sum = 1;
        int ll = arr[1], rr = -1;
        for (int i = 2; i <= n; ++ i)
        {
            if(arr[i] == ll && arr[i] != rr)
            {
                rr = arr[i];
                sum++;
            }
            else if(arr[i] != ll && arr[i] == rr)
            {
                ll == arr[i];
                sum++;
            }
            else if(arr[i] != ll && arr[i] != rr)
            {
                if(i+1 <= n && arr[i+1] == rr)
                {
                    rr = arr[i];
                    sum++;
                }
                else
                {
                    ll = arr[i];
                    sum++;
                }
            }
        }
        printf("%d
    ", sum);
        return 0;
    }

    D2 - Painting the Array II

    Problem 1479B2 - Painting the Array II

    给定一个序列a,需要分成a1,a2两个序列,每个数只能被分到一个序列中,且同意序列中的数相对位置不变。定义seg(a)为将序列中相邻值相等的数合并后序列剩下的数。求min(seg(a1)+seg(a2))

    Solution

     待补

    Code

    E - Continuous City

    Problem 1479C - Continuous City

    Solution

    待补

    Code

  • 相关阅读:
    UE 不生成.bak文件
    DOTWeen 使用
    unity admob
    UGUI 判断元素进入舞台
    unity 解决ScrollRect嵌套滚动问题
    oc字符串与c字符串转换和拷贝
    Object-c中的单例
    JAVA比较两个List集合的方法
    CentOS 7 配置静态IP
    CentOS7安装Jdk1.8
  • 原文地址:https://www.cnblogs.com/wifePI/p/14398023.html
Copyright © 2020-2023  润新知