Codeforces Round #700 (Div. 2)A~D2解题报告

Codeforces Round #700 (Div. 2)A~D2解题报告

A Yet Another String Game

原题链接

http://codeforces.com/contest/1480/problem/A
在这里插入图片描述

在这里插入图片描述

解题思路

  • Alice想让更小,先手
  • Bob想让其更大,后手
  • 解决方案当然是贪心,从第一个排到最后一个
  • 如果不是选择当前未更改的第一个,那么被别人修改,那么就会往反方向走了

AC代码

#include <bits/stdc++.h>
using namespace std;

const int N = 110;
char s[N];

int main()
{
    int t;  cin >> t;
    while (t -- )
    {
        scanf("%s", s);
        for (int i = 0; s[i]; i ++ )
        {
            if (i & 1)  // bigger
            {
                if (s[i] != 'z')
                    putchar('z');
                else
                    putchar('y');
            }
            else        // smaller
            {
                if (s[i] != 'a')
                    putchar('a');
                else
                    putchar('b');
            }
        }
        puts("");
    }

    return 0;
}


B The Great Hero

原题链接

http://codeforces.com/contest/1480/problem/B
在这里插入图片描述
在这里插入图片描述

解题思路

就是一个英雄和一群小怪兽打,机制和洛克王国一样,问自己安排小怪兽出厂顺序,是否可以打死所有小怪兽(包括同归于尽)。
我们一直英雄的伤害为 A A A,血量为 B B B, n n n个小怪兽的伤害为 a i a_i ai,血量为 b i b_i bi,可以计算出他可以承受的伤害为 c i = ⌈ b i / A ⌉ c_i=\lceil b_i/A\rceil ci=bi/A
英雄可以打过的充要条件是:
A > c 1 ∗ a 1 + . . . + c i ∗ a i + . . . + ( ( c n − 1 ) ∗ a n ) A > c_1*a_1 +...+c_i * a_i +... +((c_n - 1)* a_n) A>c1a1+...+ciai+...+((cn1)an) 注意这里是大于,因为保证最后一下可以打出去就行
⟹ \Longrightarrow
A + a n > c 1 ∗ a 1 + . . . + c i ∗ a i + . . . + ( c n ∗ a n ) A + a_n > c_1*a_1 +...+c_i * a_i +... +(c_n * a_n) A+an>c1a1+...+ciai+...+(cnan)
右边是常数,左面越大越好,也就是攻击力最大的放在最后即可
O ( N ) O(N) O(N)

AC代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 100010;
int n;
LL A, B;
class Node
{
public:
    int a, b;
}q[N];


int main()
{
    int t;  cin >> t;
    while (t -- )
    {
        scanf("%lld%lld", &A, &B);
        scanf("%d", &n);
        int tmp;
        int max_a = 0;
        for (int i = 1; i <= n; i ++ )
        {
            scanf("%d", &q[i].a);
            max_a = max(max_a, q[i].a);
        }

        LL sum = 0;
        for (int i = 1; i <= n; i ++ )
        {
            scanf("%d", &tmp);
            q[i].b = tmp / A + (tmp % A != 0);  // 可以几回合
            sum = sum + LL(q[i].a) * q[i].b;
        }

        if (B + max_a > sum)
            puts("YES");
        else
            puts("NO");
    }

    return 0;
}


C Searching Local Minimum

原题链接

http://codeforces.com/contest/1480/problem/C
在这里插入图片描述
在这里插入图片描述

解题思路

二分题目
这个题目二分特性很难一眼看出,平时的二分基本是左侧为满足(不满足),右侧是不满足(满足),然后进行二分,有意思的地方就是在于满足的是什么特性!!
本题这个特性和平时遇到的特性不同, 特性是:区间[l,r]中至少含有一个local_min,至少含有一个是精髓! 因为对于本体而言局部最小值可能有很多,而且还很分散,我们需要找任意一个局部最小值,直接按照这个性质来找就可以二分。
需要注意的一点是,被我们舍弃的另一部分不是说不含有local_min,而是在我们未询问的前提下可能不含有local_min,而选中的那个区间一定含有。

AC代码

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 100010, INF = 0x3f3f3f3f;
int a[N];

void query(int idx)
{
    if (a[idx] != -1)       // 之前已经是有数字了
        return;

    printf("? %d\n", idx);
    cout.flush();
    scanf("%d", &a[idx]);
}
int n;

int main()
{
    cin >> n;
    memset(a, -1, sizeof a);
    a[0] = INF, a[n + 1] = INF;

    int l = 1, r = n, mid;
    while (l < r)
    {
        mid = (l + r) / 2;
        query(mid);
        query(mid + 1);
        if (a[mid] < a[mid + 1])
        {
            r = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    printf("! %d\n", l);
    return 0;
}


D1 Painting the Array I

原题链接

http://codeforces.com/contest/1480/problem/D1
样例

解题思路

题目大概描述为,将原本的数组 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an通过染色分成两个子数组 a 1 ( 0 ) , a 2 ( 0 ) , . . . , a n 1 ( 0 ) a_1^{(0)}, a_2^{(0)}, ..., a_{n1}^{(0)} a1(0),a2(0),...,an1(0) a 1 ( 1 ) , a 2 ( 1 ) , . . . , a n 1 ( 1 ) a_1^{(1)}, a_2^{(1)}, ..., a_{n1}^{(1)} a1(1),a2(1),...,an1(1)使得合并数组毗邻相同的元素后,两个数组的长度和尽可能的大。
下面我们对原数组变形,形成以下形式
a 0 , ⋅ ⋅ ⋅ , a 0 ⏟ n 0 , a 1 , ⋅ ⋅ ⋅ , a 1 ⏟ n 1 , ⋅ ⋅ ⋅ a i , ⋅ ⋅ ⋅ , a i ⏟ n i , ⋅ ⋅ ⋅ , a e d , ⋅ ⋅ ⋅ , a e d ⏟ n e d \underbrace{a_0, \cdot\cdot\cdot, a_0}_{n_0},\underbrace{a_1, \cdot\cdot\cdot, a_1}_{n_1},\cdot\cdot\cdot\underbrace{a_i, \cdot\cdot\cdot, a_i}_{n_i},\cdot\cdot\cdot,\underbrace{a_{ed}, \cdot\cdot\cdot, a_{ed}}_{n_{ed}} n0 a0,,a0,n1 a1,,a1,ni ai,,ai,,ned aed,,aed \quad 其中 ∀ i , a i ≠ a i + 1 \forall i, a_i \not= a_{i+1} i,ai=ai+1
假设我们当前正要处理 a i , ⋅ ⋅ ⋅ , a i ⏟ n i , \underbrace{a_i, \cdot\cdot\cdot, a_i}_{n_i}, ni ai,,ai,部分时,分配的两个数组当前为 b 1 , b 2 , ⋅ ⋅ ⋅ , b c u r 1 b_1,b_2,\cdot\cdot\cdot,b_{cur1}\quad b1,b2,,bcur1 c 1 , c 2 , ⋅ ⋅ ⋅ , c c u r 2 \quad c_1,c_2,\cdot\cdot\cdot,c_{cur2} c1,c2,,ccur2
下面我们对当前处理的情况进行讨论,

  • n i = 1 n_i=1 ni=1
    b c u r 1 和 c c u r 2 至 少 存 在 一 个 不 等 于 a i b_{cur1}和c_{cur2}至少存在一个不等于a_{i} bcur1ccur2ai,那么直接放在不等于的后面, r e s + = 1 res += 1 res+=1
  • n i ≥ 2 n_i\geq 2 ni2
    b c u r 1 和 c c u r 2 存 在 一 个 等 于 a i , 另 一 个 不 等 于 a i \quad b_{cur1}和c_{cur2}存在一个等于a_{i},另一个不等于a_{i} bcur1ccur2aiai,那么直接放在不等于的后面(两边都放也行), r e s + = 1 \quad \quad res += 1 res+=1
    b c u r 1 和 c c u r 2 都 不 等 于 a i \quad b_{cur1}和c_{cur2}都不等于a_{i} bcur1ccur2ai,那么两边都放至少一个, r e s + = 2 \quad res += 2 res+=2
    那么为什么这样做是对的?

补证明:

AC代码

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;
const int INF = 0x3f3f3f3f;
int a[N];
int n;
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )
        scanf("%d", &a[i]);

    int pre = 1, ed = 0, cnt;
    a[0] = a[n + 1] = a[n + 2] = a[n + 3] = INF;
    int res = 0;
    int surp1 = -INF, surp2 = -INF;
    int tmp1;
    for (int i = 1; i <= n + 1; i ++ )
    {
        if (a[i] == a[i - 1])
        {
            ed = i;
        }
        else
        {
            cnt = ed - pre + 1;
            if (cnt == 0)
            {
                pre = ed = i;
                continue;
            }

            if (surp1 == a[i - 1] || surp2 == a[i - 1])
            {
                surp1 = surp2 = a[i - 1];
                res += 1;
            }
            else if (cnt >= 2)
            {
                res += 2;
                surp1 = surp2 = a[i - 1];
            }
            else if (cnt == 1)  // 帮忙遮掩
            {
                tmp1 = a[i];
                if (surp1 == a[i])
                    surp1 = a[i - 1];
                else if (surp2 == a[i])
                    surp2 = a[i - 1];
                else
                    surp1 = a[i - 1];
                res += 1;
            }
            pre = ed = i;
        }
    }
    cout << res << endl;
    return 0;

}


D2 Painting the Array II

原题链接 待补

http://codeforces.com/contest/1480/problem/D2
在这里插入图片描述

解题思路

该题目也是贪心,
首先,原数组 a 0 , ⋅ ⋅ ⋅ , a 0 ⏟ n 0 , a 1 , ⋅ ⋅ ⋅ , a 1 ⏟ n 1 , ⋅ ⋅ ⋅ a i , ⋅ ⋅ ⋅ , a i ⏟ n i , ⋅ ⋅ ⋅ , a e d , ⋅ ⋅ ⋅ , a e d ⏟ n e d \underbrace{a_0, \cdot\cdot\cdot, a_0}_{n_0},\underbrace{a_1, \cdot\cdot\cdot, a_1}_{n_1},\cdot\cdot\cdot\underbrace{a_i, \cdot\cdot\cdot, a_i}_{n_i},\cdot\cdot\cdot,\underbrace{a_{ed}, \cdot\cdot\cdot, a_{ed}}_{n_{ed}} n0 a0,,a0,n1 a1,,a1,ni ai,,ai,,ned aed,,aed \quad 其中 ∀ i , a i ≠ a i + 1 \forall i, a_i \not= a_{i+1} i,ai=ai+1。因为是要求最小,我们将数组改造为 a 0 , a 1 , ⋅ ⋅ ⋅ , a i , ⋅ ⋅ ⋅ , a e d a_0, a_1, \cdot \cdot \cdot,a_i, \cdot \cdot \cdot,a_{ed} a0,a1,,ai,,aed
假设我们当前构造的两行 l i n e 1 , l i n e 2 line1, line2 line1,line2是正确的,现在查看 a [ i ] a[i] a[i]应该放在哪个队列之后。

  • l i n e 1 _ b a c k ( ) = l i n e 2 _ b a c k ( ) line1\_back() =line2\_back() line1_back()=line2_back(),那么我们将 a [ i ] a[i] a[i]放在那里都是可以的。
  • l i n e 1 _ b a c k ( ) ≠ l i n e 2 _ b a c k ( ) line1\_back() \not=line2\_back() line1_back()=line2_back()时候,进行下列分析
    倘若 l i n e 1 _ b a c k ( ) = a [ i ] line1\_back() = a[i] line1_back()=a[i],那么直接放在 l i n e 1 line1 line1即可,因为可以直接抵消掉
    同理,倘若 l i n e 2 _ b a c k ( ) = a [ i ] line2\_back() = a[i] line2_back()=a[i],那么直接放在 l i n e 2 line2 line2即可。
    最后 一种情况, l i n e 1 _ b a c k ( ) ≠ a [ i ] 而 且 l i n e 2 _ b a c k ( ) ≠ a [ i ] line1\_back() \not= a[i] 而且 line2\_back() \not= a[i] line1_back()=a[i]line2_back()=a[i],那么我们考虑 l i n e 1 line1 line1 l i n e 2 line2 line2的末尾谁可以最近的匹配,放入较远的一方即可。(因为最近匹配优先,不可被中断)。

AC代码

#include <bits/stdc++.h>
using namespace std;

const int N = 100010, INF = 0x3f3f3f3f;
int a[N], b[N];
int n;
vector<int> pos[N];
int cur[N];

int nxt(int x)
{
    if (x == INF || cur[x] == pos[x].size())    // 已经到达了最后一个
        return INF;
    else
        return pos[x][cur[x]];
}

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )  scanf("%d", &a[i]);
    int n2 = 1;
    b[1] = a[1];
    for (int i = 2; i <= n; i ++ )
        if (a[i] != a[i - 1])
            b[++ n2] = a[i];
    n = n2;
    memset(cur, 0, sizeof cur);

    for (int i = 1; i <= n; i ++ )
    {
        // printf("%d ", b[i]);
        pos[b[i]].push_back(i);
    }
    // puts("");

    int res = n;
    vector<int> v[2];
    int tar = INF, cur_tar, tar_line = 1;
    v[0].push_back(INF), v[1].push_back(INF);

    for (int i = 1; i <= n; i ++ )
    {
        cur[b[i]] ++;
        if (v[0].back() == v[1].back()) // 情况一,line1 == line2
        {
            if (v[0].back() == b[i])
                res --;
            v[0].push_back(b[i]);
        }
        else if (v[0].back() == b[i])
        {
            res --;
            v[0].push_back(b[i]);
        }
        else if (v[1].back() == b[i])
        {
            res --;
            v[1].push_back(b[i]);
        }
        else
        {
            static int nxt0, nxt1;
            nxt0 = nxt(v[0].back());
            nxt1 = nxt(v[1].back());
            if (nxt0 >= nxt1)
            {
                v[0].push_back(b[i]);
            }
            else
            {
                v[1].push_back(b[i]);
            }
        }
    }

    cout << res << endl;
    return 0;
}
/*
15
1 1 1 2 2 1 3 2 1 1 1 2 3 3 1
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 JavaScript 编写的记忆游戏(附源代码)   项目:JavaScript 记忆游戏(附源代码) 记忆检查游戏是一个使用 HTML5、CSS 和 JavaScript 开发的简单项目。这个游戏是关于测试你的短期 记忆技能。玩这个游戏 时,一系列图像会出现在一个盒子形状的区域中 。玩家必须找到两个相同的图像并单击它们以使它们消失。 如何运行游戏? 记忆游戏项目仅包含 HTML、CSS 和 JavaScript。谈到此游戏的功能,用户必须单击两个相同的图像才能使它们消失。 点击卡片或按下键盘键,通过 2 乘 2 旋转来重建鸟儿对,并发现隐藏在下面的图像! 如果翻开的牌面相同(一对),您就赢了,并且该对牌将从游戏中消失! 否则,卡片会自动翻面朝下,您需要重新尝试! 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox, 以获得更好、更优化的游戏体验。要玩游戏,首先,通过单击 memorygame-index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值