Codeforces Round #609

Long Beautiful Integer

题目链接 http://codeforces.com/contest/1268/problem/A

题意

给出一个 n 位数字 x,求 >= 它的最小的美丽数字。
美丽数字定义为:
对于给定的 k,第 i 位数字有 \(b_i = b_{i+k}\)。

题解

可见,所求数字每 k 位重复,先使高 k 位等于 x 的高 k 位,判断能否满足大于等于的要求,不能的话增大第 k 位。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define Nmax 200010
int N;
int A[Nmax];
int K;
int main() {
    scanf("%d %d", &N, &K);
    for (int i = 1; i <= N; i++)
        scanf("%1d", &A[i]);
    bool F = false;
    for (int i = K+1; i <= N; i++) {
        if (A[i] > A[(i-1)%K+1]) {
            F = true;
            break;
        }
        else if (A[i] < A[(i-1)%K+1])
            break;
    }
    if (F) {
        for (int i = K; i >= 1; i--) {
            if (F) {
                if (A[i] != 9) {
                    A[i]++;
                    F = false;
                }
                else {
                    A[i] = 0;
                }
            }
            else
                break;
        }
    }
    printf("%d\n", N);
    for (int i = 1; i <= N; i++)
        printf("%01d", A[(i-1)%K+1]);
    return 0;
}

Domino for Young

题目链接 http://codeforces.com/contest/1268/problem/B

题意

给出一个棋盘,第 i 列的高度为 \(a_i\),求用 1x2 骨牌覆盖,最多能放多少个骨牌。

题解

对棋盘黑白染色,黑格和白格数的最小值为答案。
证明:
对于长度相等的两行或者两列,显然可以用骨牌横向覆盖,这部分黑白格数相等。
反复这种覆盖,最后只剩单调递减到 1 的序列。
显然在这种最简情况下黑白格数最小值为答案。

代码

#include <cstdio>
#include <algorithm>
using namespace std;
#define Nmax 300010
int N;
int ls[Nmax];
long long B[2];
int main() {
    scanf("%d", &N);
    int a;
    for (int i = 1; i <= N; i++) {
        scanf("%d", &a);
        B[i%2] += a/2;
        B[(i+1)%2] += a - a/2;
    }
    printf("%lld\n", min(B[0], B[1]));
    return 0;
}

K Integers

题目链接 http://codeforces.com/contest/1268/problem/C

题意

给出 n 个数的一个排列,每次交换两个相邻数字。
对于每个的 k 属于 1~n,求将 1~k 这 k 个数交换到相邻递增需要的交换次数。

题解

分解问题,首先要让这 k 个数相邻,然后使他们的相对位置正确。
让这 k 个数相邻,显然移动到 k 个数所在位置的中位数附近最优,使用两个优先队列维护中位数。
调整相对位置,变成普通的求排序时交换次数的问题,对于 n 个不同的询问,求出每个新增的数 k 之后有多少个小于它的数(新增逆序对数)。

代码

#include <cstdio>
#include <queue>
using namespace std;
#define Nmax 200010
int N;
int ls[Nmax];
priority_queue<int> qb, qs;
long long bsm, ssm;
int sm[Nmax];
inline int lowbit(int x) {
    return x&-x;
}
void adin(int x) {
    for (int i = x; i <= N; i += lowbit(i))
        sm[i] += 1;
}
int qin(int x) {
    int ans = 0;
    for (int i = x; i; i -= lowbit(i))
        ans += sm[i];
    return ans;
}
int main() {
    scanf("%d", &N);
    int a;
    for (int i = 1; i <= N; i++) {
        scanf("%d", &a);
        ls[a] = i;
    }
    long long ans = 0;
    long long ans2;
    for (int k = 1; k <= N; k++) {
        if (qb.size() && ls[k] < qb.top()) {
            qb.push(ls[k]);
            bsm += ls[k];
        }
        else {
            qs.push(-ls[k]);
            ssm += ls[k];
        }
        while (qb.size() < qs.size()) {
            a = -qs.top();
            qs.pop();
            ssm -= a;
            qb.push(a);
            bsm += a;
        }
        while (qb.size() > qs.size()+1) {
            a = qb.top();
            qb.pop();
            bsm -= a;
            qs.push(-a);
            ssm += a;
        }
        adin(ls[k]);
        ans += k - qin(ls[k]);
        a = qb.top();
        ans2 = ans
                + (long long)qb.size()*a-bsm - (0LL+qb.size()-1)*qb.size()/2
                + ssm-(long long)qs.size()*a - (1LL+qs.size())*qs.size()/2;
        printf("%lld ", ans2);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/KZNS/p/codeforces-round-609.html