• Codeforces Global Round 13 Editorial补题


       A. K-th Largest Value

    题意:数组a有n个0或者1,给q次操作,操作有两种,第一种ax->1-ax,第二种输出第k大元素

    题解:标准水题,统计1的个数,进行第一种操作的时候更新1的个数即可,输出第k大元素时,看有无k个1,有就输出1,无就输出0

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn = 1e5+10;
    int a[maxn];
    int num;
    int main()
    {
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i = 1; i <= n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]) num++;
        }
        for(int i = 0; i < q;i++)
        {
            int id;
            scanf("%d",&id);
            if(id == 1)
            {
                int x;
                scanf("%d",&x);
                a[x] = 1 - a[x];
                if(a[x] == 1)
                num++;
                else num--;
            }
            else
            {
                int x;
                scanf("%d",&x);
                if(x <= num)
                printf("1
    ");
                else printf("0
    ");
            }
        }
        //system("pause");
        return 0;
    }

     B. Minimal Cost

     

    题意:给定n行,106+2列,每一行有一个障碍,障碍不出现在第0行和第106+1行,可以花费费用u垂直移动障碍,花费费用v水平移动障碍,问对该网络一个人可以从左上角走到右下角,最小花费

    题解:分类讨论,如果所有障碍在同一列,那么要么平移两次,要么平移一次垂直动一次,答案为min(2*v,u+v);如果存在相邻行障碍所在列差值最大为1,那么要么平移一次,要么垂直移一次,答案为min(u,v);如果存在相邻行所在列差值大于等于2,答案为0

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn = 1e6+10;
    int a[maxn];
    int num;
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int i=0; i<t; i++)
        {
            memset(a,0,sizeof(a));
            int n;
            ll u,v;
            scanf("%d%lld%lld",&n,&u,&v);
            int ok = 1;
            int ansok = 1;
            int last = 0;
            for(int i = 0; i < n; i++)
            {
                scanf("%d",&a[i+1]);
                if(i != 0)
                {
                    if(a[i+1] != last)
                    ok = 0;
                    if(abs(a[i+1] - a[i]) >=2 )
                    ansok = 0;
                }
                last = a[i+1];
            }
            if(!ansok)
            printf("0
    ");
            else
            if(ok)
            {
                printf("%lld
    ",min(2*v,u+v));
            }
            else
            printf("%lld
    ",min(u,v));
        }
        //system("pause");
        return 0;
    }

      C. Pekora and Trampoline

     

    题意:给定一个长度为n的序列S,一个人可以从任何位置i起跳,下一步跳到i+Si,一直跳直到跳出n,每在一个位置i跳一次,对应位置Si减一,问多少次这个人会把序列S跳为全1

    题解:贪心,每轮从前面的Si不为1的位置i起跳最优,并且该位置的Si一定会跳到1,那么对[i+2,min(i+Si,n)]这个区间的所有位置的Si都有-1的贡献,并且如果该位置的Si已经跳到1后,如果还跳到这个位置x次,那么一定对位置i+1有-x的贡献。

    设立数组last[i],代表位置i已经被踩了多少次。从头遍历所有位置,寻找起跳点,对于当前的起跳点i,对答案ans的贡献为ans = S[i] - last[i] - 1(这样该点的Si会跳为1),last[i]更新为last[i] += S[i] - last[i] -1,对last[i+1]的贡献为last[i+1] += last[i] - S[i] + 1(跳到1后还跳了几次),对S[j]的贡献为S[j] - 1,j ∈ [i+2,min(i+Si,n)]。

    code:

     D. Zookeeper and The Infinite Zoo

    题意:u可以达到u+v的充要条件为u&v = v,给定一系列a、b,问a能否到达b

    题解:

    ①首先确定这不是图论!【好像没什么卵用的发现】

    ②通过观察发现u&v = v这个条件代表着u和从u自身二进制为1的那些位取出部分组成的数相&,一定满足u&v = v(例如u = 000111,v = 000100/000010/000001/000110等都满足条件)  【好像也是没什么卵用的发现】

    ③如果能够从u到达x;根据位运算的知识,u的任何一位1都可以通过相加进行左移,但不可以右移,也就是如果x的1的位置在u的1的位置的左边,就可以从u到达v

    写法:从右往左比对x和u的每一位i,如果u[i] = 1,num++,如果x[i] = 1,num--,如果在某一位num < 0,那么不可达,否则可达(例如000010可以达到001000,是因为从右侧开始i = 2时, num + 1= 1,到了i = 4时, num - 1 = 0,一直是合法的。显然x[4]的1,可以通过u[2]的1不断左移得到)

    [代码写的太丑,一会放个写得简洁的]

    code:

  • 相关阅读:
    WPF:DataGrid 自动生成行号
    C#:WinForm之Command
    i.MX RT1010之FlexIO模拟SSI外设
    i.MX RT1010之FlexIO模拟I2S外设
    i.MX RT600之DSP开发环境调试篇
    i.MX RT600之DSP调试环境搭建篇
    i.MX RT600之DMIC外设介绍及应用
    i.MX RT600之I2S外设介绍及应用
    ssm框架思维-登录
    idea里面搭建SSM框架-crud
  • 原文地址:https://www.cnblogs.com/VAthree/p/14466735.html
Copyright © 2020-2023  润新知