Codeforces Round #700 (Div. 2)

A. Yet Another String Game

#include<bits/stdc++.h>
using namespace std;
char s[60];
int main()
{
    int t;
    scanf("%d", &t);
    while (t--){
        scanf("%s", s);
        int i, l = strlen(s);
        for (i = 0; i < l; i++){
            if (i % 2 == 0){
                if (s[i] != 'a') s[i] = 'a';
                else s[i] = 'b';
            }
            else{
                if (s[i] != 'z') s[i] = 'z';
                else s[i] = 'y';
            }
        }
        printf("%s\n", s);
    }
}

B. The Great Hero
题解:假设英雄能打败所有怪兽,最极端的情况是英雄用最后一滴血打败了攻击力最高的怪兽,那么前n-1只怪兽则是用B-1点血打败。所以,如果B-1+(ai)max>=damage(所有怪兽对英雄的伤害),英雄就能打败所有怪兽。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100010];
ll b[100010];
int main()
{
    int t, aa, bb, n, i;
    scanf("%d", &t);
    while (t--){
        ll mx = 0, damage = 0;
        scanf("%d%d%d", &aa, &bb, &n);
        for (i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
            mx = max(mx,a[i]);
        }
        for (i = 1; i <= n; i++){
            scanf("%lld", &b[i]);
            damage += (b[i] + aa - 1) / aa * a[i];
        }
        if (bb - 1 + mx >= damage) printf("YES\n");
        else printf("NO\n");
    }
}

C. Searching Local Minimum
题意:有1~n的n个长度的序列,开始被隐藏掉了,每查询一次恢复一个数,最多查询一百个位置,求一个k,k满足ak < ak-1、ak < ak+1。
交互格式:输入一个n,之后不断地输出"? i"、输入ai,直到找到满足条件的k为止并输出"! k"。ai唯一,下标不唯一。交互题一般用二分做。
题解:设一个位置mid。
1.a(mid) < a(mid+1),往右找到一个数x,使得a(mid) < a(mid+1)、a(mid) < x,k = mid。
2.a(mid)<a(mid+1),往左找到一个数y,使得y < a(mid)、y < a(mid+1),k = mid。

#include<bits/stdc++.h>
using namespace std;
int a[100010];
int n;
void query(int x)
{
    if (1 <= x && x <= n){//防止越界
        printf("? %d\n", x);
        fflush(stdout);
        scanf("%d", &a[x]);
    }
}
int main()
{
    scanf("%d", &n);
    a[0] = a[n + 1] = n + 1;
    int l = 1, r = n, mid, ans;
    while (l <= r){
        mid = (l + r) / 2;
        query(mid);
        query(mid + 1);
        if (a[mid] < a[mid + 1]){
            ans = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    printf("! %d\n", ans);
    fflush(stdout);
}

D1. Painting the Array I
题意:将a序列分为a0和a1序列,每个序列相邻重复的数合并为一个,求两个序列中最大的不同元素个数之和。
题解:因为要求最大长度,那么相邻的元素应当尽可能的不同。设a[x]为a0序列中最后一个元素,a[y]为a1序列中最后一个元素,next[i]为第i位后下一个和a[i]相同的元素。分为以下三种情况:
1.a[i]和a[x]、a[y]都相同:a[i]放a[x]或a[y]后面都可以。
2.a[i]和a[x]、a[y]其中一个相同:若a[i]和a[x]相同,a[i]放在a[y]后面;若a[i]和a[y]相同,a[i]放在a[x]后面。
3.a[i]和a[x]、a[y]都不相同:若next[x]<next[y],a[i]放在a[x]后面;若next[y]<next[x],a[i]放在a[y]后面。(位置靠近的即相邻的元素要尽可能的不同,相当于用不同的元素把相同的替换掉)

#include<bits/stdc++.h>
using namespace std;
int a[100010];
int pos[100010];
int nxt[100010];//next莫名ce
int main()
{
    int n, i;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for (i = 0; i <= n; i++)
        pos[i] = n + 1;
    for (i = n; i >= 0; i--){
        nxt[i] = pos[a[i]];
        pos[a[i]] = i;
    }
    int x = 0, y = 0, res = 0;
    for (i = 1; i <= n; i++){
        if (a[i] == a[x]){//第一种情况包括在第二种情况里
            res += a[i] != a[y];
            y = i;
        }
        else if (a[i] == a[y]){//第二种情况
            res++;
            x = i;
        }
        else if (nxt[x] < nxt[y]){//第三种情况
            res++;
            x = i;
        }
        else{
            res++;
            y = i;
        }
    }
    printf("%d\n", res);
}

D2. Painting the Array II
题解:求最小长度,相邻元素要尽可能的相同。跟上题条件反一下即可。

#include<bits/stdc++.h>
using namespace std;
int a[100010];
int pos[100010];
int nxt[100010];
int main()
{
    int n, i;
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    for (i = 0; i <= n; i++)
        pos[i] = n + 1;
    for (i = n; i >= 0; i--){
        nxt[i] = pos[a[i]];
        pos[a[i]] = i;
    }
    int x = 0, y = 0, res = 0;
    for (i = 1; i <= n; i++){
        if (a[i] == a[x]){
            x = i;
        }
        else if (a[i] == a[y]){
            y = i;
        }
        else if (nxt[x] > nxt[y]){
            res += a[i] != a[y];
            x = i;
        }
        else{
            res += a[i] != a[x];
            y = i;
        }
    }
    printf("%d\n", res);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值