CF1215E Marbles 状压dp

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_40758751/article/details/101103559

E. Marbles

time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Monocarp has arranged nn colored marbles in a row. The color of the ii-th marble is aiai. Monocarp likes ordered things, so he wants to rearrange marbles in such a way that all marbles of the same color form a contiguos segment (and there is only one such segment for each color).

In other words, Monocarp wants to rearrange marbles so that, for every color jj, if the leftmost marble of color jj is ll-th in the row, and the rightmost marble of this color has position rr in the row, then every marble from ll to rr has color jj.

To achieve his goal, Monocarp can do the following operation any number of times: choose two neighbouring marbles, and swap them.

You have to calculate the minimum number of operations Monocarp has to perform to rearrange the marbles. Note that the order of segments of marbles having equal color does not matter, it is only required that, for every color, all the marbles of this color form exactly one contiguous segment.

Input

The first line contains one integer nn (2≤n≤4⋅105)(2≤n≤4⋅105) — the number of marbles.

The second line contains an integer sequence a1,a2,…,ana1,a2,…,an (1≤ai≤20)(1≤ai≤20), where aiai is the color of the ii-th marble.

Output

Print the minimum number of operations Monocarp has to perform to achieve his goal.

Examples

input

Copy

7
3 4 2 3 4 2 2

output

Copy

3

input

Copy

5
20 1 14 10 2

output

Copy

0

input

Copy

13
5 5 4 4 3 5 7 6 5 4 4 6 5

output

Copy

21

Note

In the first example three operations are enough. Firstly, Monocarp should swap the third and the fourth marbles, so the sequence of colors is [3,4,3,2,4,2,2][3,4,3,2,4,2,2]. Then Monocarp should swap the second and the third marbles, so the sequence is [3,3,4,2,4,2,2][3,3,4,2,4,2,2]. And finally, Monocarp should swap the fourth and the fifth marbles, so the sequence is [3,3,4,4,2,2,2][3,3,4,4,2,2,2].

In the second example there's no need to perform any operations.

思路:

dp[i]中位为1的表示该颜色已经排好序的最小操作数。

ma[i][j]表示,假设只有i,j两种颜色,把i全放j前面的最小移动数。

转移方程是:当前要排好第j种颜色,就等于把当前已经排好的颜色都拿到第j种前面来。

dp[当前已经排好的颜色+排好j] = min(dp[当前已经排好的颜色]+把排好第j种颜色的操作数,dp[当前已经排好的颜色+排好j] )

AC代码:

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn = 1e6+50;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 1e9+7;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
ll ma[25][25], dp[(1 << 20) + 7];
vector<int> col[25];
int main()
{
    int n;
    cin >> n;
    int temp;
    rep(i, 1, n){
        cin >> temp;
        col[temp].push_back(i);
    }

    rep(i, 1, 20){
        rep(j, 1, 20){
            if(i == j) continue;
            for(int k = 0; k < col[i].size(); k++){
                int v = col[i][k];
                if(col[j].size() == 0 || col[j][0] > v) continue;
                int st = 0, en = col[j].size();
                while(st != en){
                    int md = (st+en)/2;
                    if(col[j][md] < v){
                        st = md+1;
                    }
                    else en = md;
                }
                ma[i][j] += st;
            }
        }
    }
    int len = (1<<20);
    rep(i, 1, len-1) dp[i] = LINF;

    rep(i, 0, len-1){
        rep(j, 1, 20){
            if((i&(1<<(j-1))) == 0){
                ll res = 0;
                rep(k, 1, 20){
                    if(((1<<(k-1))&i)) res += ma[k][j];
                }
                dp[i|(1<<(j-1))] = min(dp[i] + res, dp[i|(1<<(j-1))]);
            }

        }
    }
    cout << dp[len-1] <<endl;
    return 0;
}
/*
3 4 2 3 4 2 2
3 4 3 2 4 2 2
3 3 4 2 4 2 2
3 3 4 4 2 2 2

5 5 4 4 3 5 7 6 5 4 4 6 5

*/

猜你喜欢

转载自blog.csdn.net/qq_40758751/article/details/101103559
今日推荐