[AtCoder ARC097]E - Sorted and Sorted(dp,逆序对,前缀和优化)

E - Sorted and Sorted

Time limit : 2sec / Memory limit : 1024MB
Score : 600 points

Problem Statement

There are 2 N balls, N white and N black, arranged in a row. The integers from 1 through N 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 i -th ball from the left ( 1 i 2 N ) is a i , and the color of this ball is represented by a letter c i . c i = W represents the ball is white; c i = B represents the ball is black.
Takahashi the human wants to achieve the following objective:

  • For every pair of integers ( i , j ) such that 1 i < j N , the white ball with i written on it is to the left of the white ball with j written on it.
  • For every pair of integers ( i , j ) such that 1 i < j N , the black ball with i written on it is to the left of the black ball with j 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

1 N 2000
1 a i N
c i = W or c i = B.
If i j , ( a i , c i ) ( a j , c j ) .

Input

Input is given from Standard Input in the following format:

N
c 1 a 1
c 2 a 2
:
c 2 N a 2 N

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.


解题思路

先看一个最基本的问题:

已知 1 N 的一个排列,每次操作可以交换相邻两数,求至少多少次操作才能将这个数列变为 1 , 2 , 3 , , N

答案就是原数列的逆序对对数。证明如下:
目标数列显然满足这样一个性质:对于 i [ 1 , N ) ,都有 a i < a i + 1 。因此如果当前数列不是目标数列,一定   i [ 1 , n ) 使得 a i > a i + 1 ,那么 a i a i + 1 就构成了一对逆序对,我们需要一次操作交换这两个数。这样周而复始地进行交换操作,最终操作数量就是逆序对对数。

这个基本问题就可以衍生出许多问题,比如说 NOIP2013花匠 [题解],又比如这道题。

这道题把一个 1 N 的排列变成了两个 1 N 的排列相混合,于是出现了一个问题:我们甚至都不知道最终数列的状态是怎样的。
假设现在我们知道最终数列的状态,那么只需要像 NOIP2013花匠 一样扩展一下“逆序对” ( a i , a j ) 的定义为:初始时 a i a j 之后,目标状态下 a i a j 之前的一对 ( a i , a j ) 。这样,答案仍旧是逆序对对数。
ok,现在我们只需要找到最优的目标状态了:

  • dp状态:定义 d p [ i ] [ j ] 表示目标状态中,前 i + j 个数由 1 ~ i 的黑球和 1 ~ j 的白球混合排列而成(对于任意一种颜色的球,排列是升序的)时,最少的逆序对对数
  • dp方程: d p [ i ] [ j ] = m i n ( d p [ i 1 ] [ j ] + b i , j , d p [ i ] [ j 1 ] + w i , j ) ,其中 b i , j 表示 1 ~ i 的白球和 1 ~ j 的黑球中,初始时在黑球 i 之后的球的数量; w i , j 同理
    具体计算 b i , j w i , j 可以在 dp 之前先 O ( N 2 ) 预处理出所有位置关系,再通过二维前缀和优化使得能够在 dp 时 O ( 1 ) 得值
  • dp顺序:由dp方程易知:顺序 for i 再 for j 即可
  • 边界条件:由dp定义和dp顺序可知:dp[0][0] = 0

答案即是 d p [ N ] [ N ]

时间复杂度: O ( N 2 )


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

猜你喜欢

转载自blog.csdn.net/phantomagony/article/details/80383872