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;
}