目录
1.Problem
You are given a n×nn×n chessboard. Rows and columns of the board are numbered from 11 to nn. Cell (x,y)(x,y) lies on the intersection of column number xx and row number yy.
Rook is a chess piece, that can in one turn move any number of cells vertically or horizontally. There are mm rooks (m<nm<n) placed on the chessboard in such a way that no pair of rooks attack each other. I.e. there are no pair of rooks that share a row or a column.
In one turn you can move one of the rooks any number of cells vertically or horizontally. Additionally, it shouldn't be attacked by any other rook after movement. What is the minimum number of moves required to place all the rooks on the main diagonal?
The main diagonal of the chessboard is all the cells (i,i)(i,i), where 1≤i≤n1≤i≤n.
2.Input
The first line contains the number of test cases tt (1≤t≤1031≤t≤103). Description of the tt test cases follows.
The first line of each test case contains two integers nn and mm — size of the chessboard and the number of rooks (2≤n≤1052≤n≤105, 1≤m<n1≤m<n). Each of the next mm lines contains two integers xixi and yiyi — positions of rooks, ii-th rook is placed in the cell (xi,yi)(xi,yi) (1≤xi,yi≤n1≤xi,yi≤n). It's guaranteed that no two rooks attack each other in the initial placement.
The sum of nn over all test cases does not exceed 105105.
3.Output
For each of tt test cases print a single integer — the minimum number of moves required to place all the rooks on the main diagonal.
It can be proved that this is always possible.
4.Examples
4.1input
4
3 1
2 3
3 2
2 1
1 2
5 3
2 3
3 1
1 2
5 4
4 5
5 1
2 2
3 3
4.2output
1
3
4
2
5.Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template <typename T> bool chkmax(T &x, T y) { return x < y ? x = y, true : false; }
template <typename T> bool chkmin(T &x, T y) { return x > y ? x = y, true : false; }
int readint() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
const int MAXN = 100005;
int n, x, y;
char s[MAXN];
int cnt0[MAXN], cnt1[MAXN], cntq[MAXN];
ll pre0[MAXN], pre1[MAXN], suf0[MAXN], suf1[MAXN];
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
x = readint();
y = readint();
int n0 = count(s + 1, s + n + 1, '0');
int n1 = count(s + 1, s + n + 1, '1');
ll ans = 0;
for (int i = 1; i <= n; i++) {
cnt0[i] = cnt0[i - 1] + (s[i] == '0');
cnt1[i] = cnt1[i - 1] + (s[i] == '1');
cntq[i] = cntq[i - 1] + (s[i] == '?');
if (s[i] == '0') ans += 1LL * y * cnt1[i];
else if (s[i] == '1') ans += 1LL * x * cnt0[i];
else {
pre0[i] = 1LL * y * cnt1[i] + 1LL * x * (n1 - cnt1[i]);
pre1[i] = 1LL * x * cnt0[i] + 1LL * y * (n0 - cnt0[i]);
suf0[i] = 1LL * y * cnt1[i] + 1LL * x * (n1 - cnt1[i]);
suf1[i] = 1LL * x * cnt0[i] + 1LL * y * (n0 - cnt0[i]);
}
}
for (int i = 1; i <= n; i++) pre0[i] += pre0[i - 1], pre1[i] += pre1[i - 1];
for (int i = n; i >= 1; i--) suf0[i] += suf0[i + 1], suf1[i] += suf1[i + 1];
ll now = LLONG_MAX;
for (int i = 0; i <= n; i++) {
chkmin(now, pre0[i] + suf1[i + 1] + 1LL * x * cntq[i] * (cntq[n] - cntq[i]));
chkmin(now, pre1[i] + suf0[i + 1] + 1LL * y * cntq[i] * (cntq[n] - cntq[i]));
}
printf("%lld\n", ans + now);
return 0;
}
6.Conclusion
这段代码实现了一个处理字符串的程序。具体来说,程序的作用如下:
1.通过读入一个字符串 s,以及两个整数 x 和 y,其中 x 和 y 是替换字符 '0' 和 '1' 的代价。
2.统计字符串中 '0' 和 '1' 的个数分别为 n0 和 n1。
3.通过遍历字符串,计算在每个位置上替换 '0' 和 '1' 所需要的代价,并存储在相应的数组中(如 pre0、pre1、suf0、suf1)。
4.利用前缀和数组,计算在每个位置上替换 '?' 所需要的代价,并在过程中更新最小代价 now。
5.最终输出替换所有字符的最小代价。总体来说,这段代码的目标是找到一种替换字符的方案,使得替换后的字符串的总代价最小。