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\n", 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\n");
                return;
            }
            printf("NO\n");
            return;
        }
        else
        {
            printf("NO\n");
            return;
        }
    }

    printf("YES\n");
}
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\n",x);
    ff();
    int temp;
    scanf("%d", &temp);
    return temp;
}
void out(int x)
{
    printf("! %d\n",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\n", 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

posted @ 2021-02-11 20:28  wifePie  阅读(83)  评论(0编辑  收藏  举报