ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「赛后总结」Codeforces Round #687 (Div. 2)

2020-11-30 11:01:13  阅读:256  来源: 互联网

标签:return min int Codeforces ans 687 include Round define


题意 & 题解

A.Prison Break

题意:

在二维平面中找到距离一个点最大的曼哈顿距离。

题解:

一定在矩阵的四个角上。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001
#define inf 2147483647

typedef long long ll;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

int t, n, m, r, c;

int main() {
    read(t);
    while (t--) {
        int ans = 0;
        read(n), read(m), read(r), read(c);
        ans = max(ans, abs(1 - r) + abs(1 - c));
        ans = max(ans, abs(n - r) + abs(1 - c));
        ans = max(ans, abs(1 - r) + abs(m - c));
        ans = max(ans, abs(n - r) + abs(m - c));
        printf("%d\n", ans);
    }
    return 0;
}

B.Repainting Street

题意:

给出 \(n\) 个点和一个参数 \(k\),每个点有一个颜色 \(a_i\),每次可以选择一段长为 \(k\) 的区间任意修改其中的颜色,问最少选择多少段使得颜色全部一致。

\(1\le a_i \le 100\),\(1 \le n \le 10^5\)

题解:

枚举改成什么颜色,然后贪心的选择区间,时间复杂度 \(O(n\max(a_i))\)。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001
#define inf 2147483647

typedef long long ll;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

int t, n, k, ans, a[M];

int main() {
    read(t);
    while (t--) {
        read(n), read(k); ans = inf;
        for (int i = 1; i <= n; ++i) read(a[i]);
        for (int i = 1; i <= 100; ++i) {
            int tot = 0, last = -1;
            for (int j = 1; j <= n; ++j) {
                if (a[j] == i) continue;
                if (last == -1) ++tot, last = j;
                else {
                    if (last + k - 1 >= j) continue;
                    else last = j, ++tot;
                }
            }
            ans = min(ans, tot);
        }
        printf("%d\n", ans);
    }
    return 0;
}

C.Bouncing Ball

题意:

给一个长为 \(n\) 的 \(01\) 串,可以进行两种操作:

  • 花费 \(y\) 的时间从最前面删去一个字符

  • 花费 \(x\) 的时间将一个 \(0\) 变成 \(1\)。

问最少多少时间之后 \(p,p+k,p+2k,\dots,p+qk\),其中 \(q\) 是最大的正整数使得 \(p+qk \le n\),都是 \(1\)。

题解:

从前面删去一个字符相当于让 \(p\) 往后移了一个位置,所以可以计算出从 \(p,p+1,\dots,n\) 开始的时间花费。

从 \(x\) 的位置则需要删除 \(x - p\) 个字符,时间花费为 \((x - p) \times y\)。

然后计算 \(x,x+k,x+2k,\dots,x+qk\) 位置上有 \(cnt_0\) 个字符 \(0\),时间花费为 \(cnt_0 \times x\)。

用 \(ans_i\) 表示从 \(i\) 开始的 \(cnt_0\)。

发现 \(j\) 位置如果为 \(0\),会对所有 \((x - p)\bmod k = (j-p) \bmod k\) 的 \(x\) 有贡献,可以从后往前 \(O(n)\) 处理出 \(ans\) 数组。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001
#define inf 2147483647

typedef long long ll;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

std::string s;
int t, n, p, k, x, y, ans[M];

int main() {
    read(t);
    while (t--) {
        read(n), read(p), read(k);
        std::cin >> s;
        read(x), read(y);
        int len = s.length(), minn = inf;
        for (int i = len - 1; i >= p - 1; --i) {
            int j = i + 1;
            if (s[i] == '1') {
                minn = min(ans[(j - p) % k] * x + (j - p) * y, minn);
            }
            else {
                ++ans[(j - p) % k];
                minn = min(ans[(j - p) % k] * x + (j - p) * y, minn);
            }
        }
        std::cout << minn << '\n';
        memset(ans, 0, sizeof ans);
    }
    return 0;
}

D.XOR-gun

题意:

给定一个不减的序列,每次可以选择两个相邻的数将这两个数替换为他们的异或值,序列的长度减一,问最少几次操作可以使这个序列不再满足不减。

题解:

对于三个相邻的二进制最高位相同的数可以选择后两个异或起来即可,因此想要原数列中不出现这样的情况长度不能超过 \(60\),如果超过 \(60\) 直接输出 \(1\)。

否则暴力。

经过多次操作之后一定是将 \(i\sim j\),\((j+1)\sim k\) 的异或和相比较,枚举 \(i,j,k\),时间复杂度 \(O(n^3)\)

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 100001
#define inf 2147483647

int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

int n, ans = inf, a[M], sxor[M];

int main() {
    scanf("%d", &n);
    if (n >= 100) { puts("1"); return 0; }
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        sxor[i] = sxor[i - 1] ^ a[i];
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= i; ++j) {
            for (int k = i + 1; k <= n; ++k) {
                if ((sxor[i] ^ sxor[j - 1]) > (sxor[k] ^ sxor[i])) {
                    ans = min(ans, k - i - 1 + i - j);
                }
            }
        }
    }
    if (ans == inf) puts("-1");
    else printf("%d\n", ans);
    return 0;
}

E.New Game Plus!

题意:

初始分数为 \(0\),奖励值为 \(0\),有 \(n\) 个 \(boss\),每个 \(boss\) 有一个增量 \(a_i\),打死一个 \(boss\) 后可以给分数加上现在的奖励值,并给奖励值加上 \(boss\) 的增量,你最多可以 \(k\) 次将奖励值变成 \(0\)。问能获得的最大得分。

题解:

题目可以转化成将 \(n\) 个 \(boss\) 分成 \(k+1\) 组。每组都是独立的。

对于每一组都按 \(boss\) 的增量降序排列为 \(b_1,b_2,\dots,b_m\)。

能获得的分数为 \((m-1)b_1+(m-2)b_2+\dots +b_{m-1}\)。

将 \(k-1\) 个零放到单调队列里,按增量从大到小枚举 \(boss\),从单调队列中取出最大的数加到分数中并把最大的数加上当前增量放到单调队列中。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#define M 500001

typedef long long ll;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }

ll ans;
int n, k, a[M];
std::priority_queue<ll> q;

inline void read(int &T) {
    int x = 0; bool f = 0; char c = getchar();
    while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
    while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    T = f ? -x : x;
}

bool cmp(int a, int b) { return a > b; }

int main() {
    read(n), read(k);
    for (int i = 1; i <= n; ++i) read(a[i]);
    for (int i = 1; i <= k + 1; ++i) q.push(0);
    std::sort(a + 1, a + n + 1, cmp);
    for (int i = 1; i <= n; ++i) {
        ll u = q.top(); q.pop();
        ans += u, q.push(u + a[i]);
    }
    std::cout << ans << '\n';
    return 0;
}

rating & 总结

没有 rating。

我不太行/kk

标签:return,min,int,Codeforces,ans,687,include,Round,define
来源: https://www.cnblogs.com/poi-bolg-poi/p/14060114.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有