题目大意:给出一个由N个整数组成的序列,通过每次交换相邻的两个数,使这个序列的每个相同的数都相邻。求最小的交换次数。

比如给出序列:1 2 3 2 1 ,那么最终序列应该是 1 1 2 2 3 ,最小交换次数为4.

输入格式

第一行输入一个数字n(2≤n≤4*10^5),表示大理石的总数。

第二行输入n个数字a1,a2…,an(1≤ai≤20)表示第i块大理石的颜色为ai。

输出格式

最少交换的次数。

样例

样例输入 1

7

3 4 2 3 4 2 2

样例输出 1

3

样例输入 2

5

20 1 14 10 2

样例输出 2

0

样例输入 3

13

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

样例输出 3

21

可以发现这道题的操作比较复杂,N的数量级也很大,\(N^2\)的时间复杂度肯定是行不通的。

对于这种题,我们可以先通过几组样例来构思出整道题的模型。

所以我们不妨考虑只有两种数的情况,对于数列 \(11221\),它的最终状态其实有两种\(11122\)和\(22111\)。我们统计每个数字2前面与它不同的数字的个数,分别是 2 + 2共需4次,这就是将所有的数字2全部移到左边所需要的次数,同理统计1的话只需2次。

现在我们来考虑多种数字的情况。我们发现这种情况不能直接通过上述方法来得出。但可以得到一个普遍的但不一定是最优的方法:

每次将一种数字全部移到左边,再将第二种数字全部移到左边(这时我们不能考虑第一种数字)。。。依次类推。

但每次移动哪种数字我们却不能确定,于是可以使用状压DP。

因为题目中\(1<=A_{i}<=20\)。设当前状态为S,如果S的第\(i\)位为1,则第\(i\)种颜色已经被选过,统计答案时便不需要统计第\(i\)种。

(大致思路已经给出,具体变量的含义请见注释)

#include <bits/stdc++.h>
using namespace std; #define N 400010
#define M 30
#define LL long long int A[N],n,pre[M][M];
LL f[1<<21];
vector<int> chos[M]; int main() {
cin>>n;
for(LL i=1;i<=n;i++) {
cin>>A[i];
chos[A[i]].push_back(i);//统计每种数字的下标,放入vector储存
}
//预处理
for(LL i=1;i<=20;i++)
for(LL j=1;j<=20;j++) {
if(i==j || chos[i].size()==0 || chos[j].size()==0) continue;
//统计答案
for(LL k=0,v;k<chos[i].size();k++) {
v=chos[i][k];
if(v<chos[j][0]) continue;
pre[i][j]+=lower_bound(chos[j].begin(),chos[j].end(),v)-chos[j].begin();
//二分查找离当前数字最近的指定的下标,这就是需要交换的次数,进行累加
}
}
memset(f,0x3f,sizeof(f));
f[0]=0;
for(LL i=0;i<(1<<20);i++)
for(LL j=1;j<=20;j++) //DP部分
if(!(i&(1<<(j-1)))) {
LL sum=0;
for(LL k=0;k<20;k++)
if(i&(1<<k))
sum+=pre[k+1][j];
f[i|(1<<(j-1))]=min(f[i|(1<<(j-1))],f[i]+sum);
}
cout<<f[(1<<20)-1];
}

codeforces#1215E. Marbles(状压DP)的更多相关文章

  1. E. Marbles 状压dp

    E. Marbles 这个是一个状压dp 题目大意是:给你一个数组,数组的数在1到20之间,有一个操作就是交换相邻的两个数,问 让所有相同的数相邻的最小操作次数 dp[s] 表示s状态下的操作次数,w ...

  2. codeforces 11D(状压dp)

    传送门:https://codeforces.com/problemset/problem/11/D 题意: 求n个点m条边的图里面环的个数 题解: 点的范围只有19,很容易想到是状压. dp[sta ...

  3. Codeforces Round #585 (Div. 2) E. Marbles(状压dp)

    题意:给你一个长度为n的序列 问你需要多少次两两交换 可以让相同的数字在一个区间段 思路:我们可以预处理一个数组cnt[i][j]表示把i放到j前面需要交换多少次 然后二进制枚举后 每次选择一个为1的 ...

  4. Codeforces 1215E 状压DP

    题意:给你一个序列,你可以交换序列中的相邻的两个元素,问最少需要交换多少次可以让这个序列变成若干个极大的颜色相同的子段. 思路:由于题目中的颜色种类很少,考虑状压DP.设dp[mask]为把mask为 ...

  5. Codeforces Round #585 (Div. 2) E. Marbles (状压DP),BZOJ大理石(同一道题)题解

    题意 林老师是一位大理石收藏家,他在家里收藏了n块各种颜色的大理石,第i块大理石的颜色为ai.但是林老师觉得这些石头在家里随意摆放太过凌乱,他希望把所有颜色相同的石头放在一起.换句话说,林老师需要对现 ...

  6. codeforces Diagrams & Tableaux1 (状压DP)

    http://codeforces.com/gym/100405 D题 题在pdf里 codeforces.com/gym/100405/attachments/download/2331/20132 ...

  7. Codeforces Gym 100015F Fighting for Triangles 状压DP

    Fighting for Triangles 题目连接: http://codeforces.com/gym/100015/attachments Description Andy and Ralph ...

  8. Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP

    Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...

  9. 状压dp Codeforces Beta Round #8 C

    http://codeforces.com/contest/8/problem/C 题目大意:给你一个坐标系,给你一个人的目前的坐标(该坐标也是垃圾桶的坐标),再给你n个垃圾的坐标,这个人要捡完所有的 ...

随机推荐

  1. JavaEE高级-JPA学习笔记

    *JPA概述 *JPA是什么? - Java Persistence API :用于对象持久化的API - Java EE 5.0平台标准的ORM规范,使得应用程序以统一的方式访问持久化层 - JPA ...

  2. Codeforces Round #569 (Div. 2) 题解A - Alex and a Rhombus+B - Nick and Array+C - Valeriy and Dequ+D - Tolik and His Uncle

    A. Alex and a Rhombus time limit per test1 second memory limit per test256 megabytes inputstandard i ...

  3. git 流程 rebase rename

    git流程: git init --bare git checkout -b develop git checkout -b feature1 feature1: git add . git comm ...

  4. 滑块QAbstractSlider

    继承于 QWidget 抽象类-必须子类化 提供的范围内的整数值 QAbstractSlider import sys from PyQt5.QtWidgets import QApplication ...

  5. PHP培训教程 PHP里10个鲜为人知但却非常有用的函数

    php里有非常丰富的内置函数,很多我们都用过,但仍有很多的函数我们大部分人都不熟悉,可它们却十分的有用.这篇文章里,兄弟连小编列举了一些鲜为人知但会让你眼睛一亮的PHP函数. levenshtein( ...

  6. 对SQL 优化,提升性能!

    对SQL 进行优化能够有效提高SQL 语句的执行效率,降低系统资源开销,是开发者提高后端系统处理能力的首选方案. 新产品上线后,随着运营推广活动的开始,业务进入快速增长期,数据库作为后端系统唯一或者主 ...

  7. Linux内核设计与实现 总结笔记(第十六章)页高速缓存和页回写

    页高速缓存是Linux内核实现磁盘缓存.磁盘告诉缓存重要源自:第一,访问磁盘的速度要远远低于访问内存. 第二,数据一旦被访问,就很有可能在短期内再次被访问到.这种短时期内集中访问同一片数据的原理称作临 ...

  8. new Date(str)返回 Invalid date问题

    var date=new Date($("input[name='mettingTime']").val().replace(/-/g, "/")); var ...

  9. 【bzoj2946】[Poi2000]公共串

    *题目描述: 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单词 l 计算最长公共子串的长度 l 输出结果 *输入: 文件的第一行是整数 n,1<=n<=5, ...

  10. webpack学习笔记二

    sourceMap 源代码与打包后的代码的映射关系.例如,在某个源文件中test.js里面有个错误,如果开启状态,那么打包后运行的报错信息就会说明是错误的具体位置,如果是关闭状态,报错后,提示的报错位 ...