• Codeforces Round #679 (Div. 2, based on Technocup 2021 Elimination Round 1)


    A

    给定(n)个数分别为(a_1,a_2,...,a_n),构造出一组(b_1,b_2,...,b_n)使得(a_1 imes b_1 + a_2 imes b_2 + ... + a_n imes b_n = 0) ((a_i)(b_i)必须是非(0)的数且不超过(100))(n)为偶数。

    (n)为偶数作为切入点,直接输出(a_{i+1})(-a_i),使得(a_i imes a_{i + 1} + a_{i + 1} imes -a_i = 0)。同理,输出(-a_{i + 1})(a_i)也可。

    
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100 + 20;
    int n;
    
    int main()
    {
    	int T;
    	scanf("%d", &T);
    	while(T --)
    	{
    		scanf("%d", &n);
    		for(int i = 1; i <= n; i += 2)
    		{
    			int x, y;
    			scanf("%d%d", &x, &y);
    			printf("%d %d ", -y, x);
    		}
    		puts("");
    	}
    	//system("pause");
    	return 0;
    }
    

    B

    对于一个(n imes m)的矩阵,给出它每行的顺序和它每列的顺序,还原这个矩阵。

    因为矩阵里的数一定是不重复的从(1)(n imes m)的数,对于每个二维坐标,记录每个数的行和列,然后反过来用二维数组的行列对应这个值,输出即可。

    
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 500 + 20;
    
    int r[N * N], c[N * N], a[N][N];
    int n, m, x;
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T --)
        {
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; ++ i)
                for(int j = 1; j <= m; ++ j)
                    scanf("%d", &x), c[x] = j;
            for(int i = 1; i <= m; ++ i)
                for(int j = 1; j <= n; ++ j)
                    scanf("%d", &x), r[x] = j;
            for(int i = 1; i <= n * m; ++ i) a[r[i]][c[i]] = i;
            for(int i = 1; i <= n; ++ i)
                for(int j = 1; j <= m; ++ j)
                    printf("%d%c", a[i][j], j == m ? '
    ' : ' ');
        }
        //system("pause");
        return 0;
    }
    

    C

    给定(n)个数,和(6)个基准数,对于(n)个数中的每一个,必须选择(6)个数中的一个作差,使得到的(n)个差值中最大差值和最小差值的差最小。

    (n)个数中每一个和(6)个基准数都做一下差,并标记一下这是第(i)个数与基准数得到的差,将这个差从小到大排序,然后双指针扫序列,当双指针区域里包含(n)个数得到的差(()每个数至少(1)())时,并且这个区域不能再缩小时,统计答案,扫完一遍序列即可得到最优解。
    写法:左指针每次固定右移,右指针往右扩展。

    
    #include <bits/stdc++.h>
    using namespace std;
    typedef pair<int, int> pii;
    const int N = 1e5 + 20;
    int n, a[7], b[N];
    
    int cnt[N], q;
    void add(int x)
    {
        ++ cnt[x];
        if(cnt[x] == 1) ++ q;
    }
    void rem(int x)
    {
        -- cnt[x];
        if(cnt[x] == 0) -- q;
    }
    
    int main()
    {
        for(int i = 1; i <= 6; ++ i) scanf("%d", &a[i]);
        scanf("%d", &n);
        for(int i = 1; i <= n; ++ i) scanf("%d", &b[i]);
        vector<pii> vec;
        for(int i = 1; i <= n; ++ i)
            for(int j = 1; j <= 6; ++ j)
                vec.push_back(make_pair(b[i] - a[j], i));
        sort(vec.begin(), vec.end());
        int res = 1e9;
        int l = 0, r = -1;
        while(l < 6 * n)
        {
            while(r + 1 < 6 * n && q != n) add(vec[++ r].second);
            if(q == n) res = min(res, vec[r].first - vec[l].first);
            rem(vec[l ++].second);
        }
        printf("%d
    ", res);
        //system("pause");
        return 0;
    }
    

    D

    给定(n)件物品,价格分别为(1,2,...,n),给定(2 imes n)次操作:

    (1:+) 将一件物品放置到货架上

    (2: - x) 将物品(x)卖出

    卖出物品的规则为每次只能售出价格最低的物品,请根据操作还原放置物品的顺序。

    对于每一次卖出,一定是选择最近的最近的放置,这次放置的限制比较小,这样选取答案一定是最优。
    使用栈去维护这些操作,每次(+)操作,将这是第几个放入和值的下限(()下限不能被取到()),初始化下限为0.
    每次(-)操作,如果栈中已经没有元素或者当前栈顶的下限 (>=)这个值,则不合法,直接输出NO.
    如果可以取出,就给栈顶元素位置填上当前取出的数,并对新栈顶修改下限,下限为当前取出的(x)和原来下限的最大值。

    
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5 + 20;
    
    int res[N],cnt;
    struct zt
    {
        int pos, val;
    };
    stack<zt> s;
    
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= 2 * n; ++ i)
        {
            char op[2];
            int x;
            scanf("%s", op);
            if(*op == '+') s.push({++ cnt, 0});
            else if(*op == '-')
            {
                scanf("%d", &x);
                if(s.empty() || x <= s.top().val) 
                {
                    printf("NO
    ");
                    return 0;
                }
                res[s.top().pos] = x;
                s.pop();
                if(!s.empty()) s.top().val = max(s.top().val, x);
            }
        }
        printf("YES
    ");
        for(int i = 1; i <= n; ++ i) printf("%d ", res[i]);
        puts("");
        //system("pause");
        return 0;
    }
    

    E

    每次施放技能,可以对敌人造成(a)点伤害,在接下来的(c)秒时间内,每秒敌人可以恢复(b)点血,技能冷却时间为(d)秒,问可以击杀敌人的最大血量是多少,如果可以击杀任意血量的敌人,输出(-1).

    首先考虑输出(-1)的情况,对于一次施放技能来说,如果总恢复血量(b imes c)都不如伤害(a)高,那么显然不论(d)冷却有多久,都可以通过很多次的技能来击杀任意血量的怪物。
    故当(a > b imes c) ,答案一定是(-1).
    考虑其他情况,当(a >= b imes c),则击杀怪物血量一定有上限,在先不考虑第一次施放技能的前提下,为了求出可以击杀的最大血量,总共可以让怪物恢复的时间为 (t = a / b),在这段时间里,可以施放技能的次数为(k = t / d),加上第一次施放技能总共打掉的血量为(a imes (k + 1)),总共回复的血量为(k imes d imes b + (k - 1) imes d imes b+ ... + d imes b = b imes k imes (k + 1) imes d / 2).
    故答案为

    [ ans = a imes (k + 1) - b imes k imes (k + 1) imes d / 2 ]

    
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    LL a, b, c, d;
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T --)
        {
            scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
            if(a > b * c) printf("-1
    ");
            else 
            {
                LL t = a / b;
                LL k = t / d;
                LL res = a * (k + 1) - b * d * k * (k + 1) / 2;
                printf("%lld
    ", res);
            }
        }
        //system("pause");
        return 0;
    }
    

    2020.11.17

  • 相关阅读:
    iOS drewRect方法
    iOS中的单例
    iOS中类别的使用
    iOS存储的三种方式
    安卓上微信闪退的一种解决方法
    [Z] 通天塔导游:各种编程语言的优缺点
    怎样面对痛苦?
    [Z] 10 种必知必会的软件开发工具
    [Z] Linux 内核同步机制
    [Z] 囚禁你的精灵(daemon)进程
  • 原文地址:https://www.cnblogs.com/ooctober/p/13994461.html
Copyright © 2020-2023  润新知