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

E - Sorted and Sorted

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

Problem Statement

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

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

1N2000 1 ≤ N ≤ 2000
1aiN 1 ≤ a i ≤ N
ci= c i = W or ci= c i = B.
If ij i ≠ j , (ai,ci)(aj,cj) ( a i , c i ) ≠ ( a j , c j ) .

Input

Input is given from Standard Input in the following format:

N N
c1 a1 a 1
c2 c 2 a2 a 2
: :
c2N a2N a 2 N

Output

Print the minimum number of operations required to achieve the objective.

Samples

InputOutput
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 1 N 的一个排列,每次操作可以交换相邻两数,求至少多少次操作才能将这个数列变为 1,2,3,,N 1 , 2 , 3 , ⋯ , N

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

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

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

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

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

时间复杂度: O(N2) 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;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值