E - Sorted and Sorted
Time limit : 2sec / Memory limit : 1024MB
Score : 600 points
Problem Statement
There are
balls,
white and
black, arranged in a row. The integers from
through
are written on the white balls, one on each ball, and they are also written on the black balls, one on each ball. The integer written on the
-th ball from the left (
) is
, and the color of this ball is represented by a letter
.
W
represents the ball is white;
B
represents the ball is black.
Takahashi the human wants to achieve the following objective:
- For every pair of integers such that , the white ball with written on it is to the left of the white ball with written on it.
- For every pair of integers such that , the black ball with written on it is to the left of the black ball with written on it.
In order to achieve this, he can perform the following operation:
- Swap two adjacent balls.
Find the minimum number of operations required to achieve the objective.
Constraints
W
or
B
.
If
,
.
Input
Input is given from Standard Input in the following format:
Output
Print the minimum number of operations required to achieve the objective.
Samples
Input | Output |
---|---|
3 B 1 W 2 B 3 W 1 W 3 B 2 |
4 |
4 B 4 W 4 B 3 W 3 B 2 W 2 B 1 W 1 |
18 |
9 W 3 B 1 B 4 W 1 B 5 W 9 W 2 B 6 W 5 B 3 W 8 B 9 W 7 B 2 B 8 W 4 W 6 B 7 |
41 |
Sample 1:
The objective can be achieved in four operations, for example, as follows:
Swap the black 3 and white 1.
Swap the white 1 and white 2.
Swap the black 3 and white 3.
Swap the black 3 and black 2.
解题思路
先看一个最基本的问题:
已知 到 的一个排列,每次操作可以交换相邻两数,求至少多少次操作才能将这个数列变为
答案就是原数列的逆序对对数。证明如下:
目标数列显然满足这样一个性质:对于
,都有
。因此如果当前数列不是目标数列,一定
使得
,那么
和
就构成了一对逆序对,我们需要一次操作交换这两个数。这样周而复始地进行交换操作,最终操作数量就是逆序对对数。
这个基本问题就可以衍生出许多问题,比如说 NOIP2013花匠 [题解],又比如这道题。
这道题把一个
到
的排列变成了两个
到
的排列相混合,于是出现了一个问题:我们甚至都不知道最终数列的状态是怎样的。
假设现在我们知道最终数列的状态,那么只需要像 NOIP2013花匠 一样扩展一下“逆序对”
的定义为:初始时
在
之后,目标状态下
在
之前的一对
。这样,答案仍旧是逆序对对数。
ok,现在我们只需要找到最优的目标状态了:
- dp状态:定义 表示目标状态中,前 个数由 ~ 的黑球和 ~ 的白球混合排列而成(对于任意一种颜色的球,排列是升序的)时,最少的逆序对对数
- dp方程:
,其中
表示
~
的白球和
~
的黑球中,初始时在黑球
之后的球的数量;
同理
具体计算 和 可以在 dp 之前先 预处理出所有位置关系,再通过二维前缀和优化使得能够在 dp 时 得值 - dp顺序:由dp方程易知:顺序 for i 再 for j 即可
- 边界条件:由dp定义和dp顺序可知:dp[0][0] = 0
答案即是
时间复杂度:
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x7fffffff;
const int N = 2005;
int n, a[N<<1], t, dp[N][N], g[N<<1][N<<1];
char c;
int cal(int x, int b, int w){
return g[x][b] - g[x-1][b] + g[x][w] - g[x][n] - g[x-1][w] + g[x-1][n];
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n << 1; i++){
scanf("%s%d", &c, &a[i]);
if(c == 'W') a[i] += n;
for(int j = 1; j < i; j++)
g[a[j]][a[i]] = 1;
}
for(int i = 1; i <= n << 1; i++)
for(int j = 1; j <= n << 1; j++)
g[i][j] += g[i-1][j] + g[i][j-1] - g[i-1][j-1];
memset(dp, 0x7f, sizeof dp);
dp[0][0] = 0;
for(int i = 0; i <= n; i++){
for(int j = 0; j <= n; j++){
if(!i && !j) continue;
dp[i][j] = min(i ? dp[i-1][j] + cal(i, i, j+n) : INF, j ? dp[i][j-1] + cal(j+n, i, j+n) : INF);
}
}
printf("%d\n", dp[n][n]);
return 0;
}