Description

BS96发布了一套有\(m\)个band柄绘的新badge,kuma先生想要拿到04的badge于是进行了抽抽抽。

kuma先生一共抽了\(n\)个badge。他把所有的badge排成一排来统计战果,出于强迫症他希望把所有相同band的badge放在一起。

kuma先生整理badge的方法是交换\(2\)个相邻的badge,现在他想知道他最少交换多少次可以达成目的。

Input

有多组数据,第一行一个数\(T\)表示数据组数,接下来每组数据有\(2\)行。

第一行两个数\(n,m\)。

第二行\(n\)个数,表示每个badge的band编号。

Output Format

对于每组数据输出一行,形如”Case #X:Y”。X为数据组数,从\(1\)开始,\(Y\)为最少的交换次数。

Sample Input

3

4 2

1 2 1 2

6 4

2 1 4 3 1 2

8 6

1 3 2 5 5 4 5 2

Sample Output

Case #1: 1

Case #2: 6

Case #3: 5

Hints

\(40\%\), \(n \le 100, m \le 6\)

\(70\%\), n \le 1000, m \le 14

\(100\%\), n \le 100000, m \le 18

首先确定了最后次序之后,这个过程就是一个冒泡排序,最少交换次数即为逆序对数目。于是这道题目便变成了一道排列dp题目。我们可以用状态压缩dp来解决。

设\(f[i]\)为状态为\(i\)时的最少逆序对数目。这个状态表示若\(a\)在集合\(i\)中,则\(a\)的最终位置已经确定排在前面一块。现在考虑我们将一个不在集合中的元素\(b\)加入集合中,我们只需要考虑\(b\)对逆序对的贡献,由于集合中已有元素最后都会放在\(b\)的前面,所以我们只需要计算在原数组中有多少\((p,q),q>p\),其中\(A_p = b,A_q \in i\)。对于特定的\(a,b\),这个贡献是可以预处理的。于是算法复杂度\(O(TM^22^M)\)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std; typedef long long ll;
#define maxn (100010)
#define maxm (20)
int T,N,M,A[maxn],suf[maxm][maxn],tmp[maxm]; ll f[1<<maxm],cor[maxm][maxm]; bool vis[1<<maxm]; inline int read()
{
int F = 1,ret = 0; char ch;
do ch = getchar(); while (!(ch >= '0'&&ch <= '9')&&ch != '-');
if (ch == '-') F = -1,ch = getchar();
do ret = ret*10+ch-'0',ch = getchar(); while (ch >= '0'&&ch <= '9');
return F*ret;
} inline void ready()
{
for (int i = 1;i <= N;++i) suf[A[i]][i] = 1;
for (int i = N-1;i;--i) for (int j = 1;j <= M;++j) suf[j][i] += suf[j][i+1];
for (int i = 1;i <= N;++i)
for (int j = 1;j <= M;++j)
cor[A[i]][j] += (ll)suf[j][i];
} inline void init()
{
memset(vis,false,1<<M);
memset(cor,0,sizeof(cor));
for (int i = 1;i < (1<<M);++i) f[i] = 1LL<<50;
for (int i = 0;i < M;++i) f[1<<i] = 0;
for (int i = 1;i <= M;++i) memset(suf[i],0,4*(N+1));
for (int i = 0;i < M;++i) vis[1<<i] = true;
} int main()
{
freopen("1590.in","r",stdin);
freopen("1590.out","w",stdout);
T = read();
for (int Case = 1;Case <= T;++Case)
{
printf("Case #%d: ",Case);
N = read(),M = read(); init();
for (int i = 1;i <= N;++i) A[i] = read();
ready();
for (register int i = 1,nn;i < (1<<M)-1;++i)
{
nn = 0;
for (register int j = 0;j < M;++j) if (i&(1<<j)) tmp[++nn] = j+1;
for (register int j = 0;j < M;++j)
if (!(i&(1<<j)))
{
ll sum = f[i];
for (register int k = 1;k <= nn;++k) sum += cor[j+1][tmp[k]];
if (f[i|(1<<j)] > sum) f[i|(1<<j)] = sum;
}
}
printf("%lld\n",f[(1<<M)-1]);
}
fclose(stdin); fclose(stdout);
return 0;
}

sjtu1590 强迫症的更多相关文章

  1. 有强迫症的我只能自己写一个json格式化工具

    缘由 为什么博客园的markdown解析出问题了啊?好奇怪啊! 一直以来在编码规范界有2大争论不休的话题,一个是关于是用空格缩进还是tab缩进的问题,一个是花括号是否换行的问题,笔者是tab缩进和花括 ...

  2. Swift 吐槽下Swift里一个逼死强迫症的语法:中缀语法

    中缀语法是OC里特有的一种,就是在函数的参数前面加一个解释词,让调用的时候明白该参数的含义 比如: -(void)processDataWithparamaA:(NSString *)paramaA ...

  3. 强迫症和拖延症患者如何应对马桶4(遨游Maxthon)“上次未关闭页面”丢失的问题

    强迫症和拖延症患者如何应对马桶4(遨游Maxthon)“上次未关闭页面”丢失的问题 用了马桶好多年,虽然一直bug不断,经常假死丢数据坑爹什么的,但是总得来说还是略有感情,不忍舍弃. 马桶一直有一个好 ...

  4. [逼死强迫症 - C&C++设计风格选择.1] : 命名规范

    1.命名规范 本系列的第一篇,命名风格本就是有关艺术审美,没有美与丑的绝对标准,本文难免带有主观选择倾向,但是会尽量保持客观的态度归纳几种主流的命名风格,仅供参考.制定规范是为了方便团队沟通和利于代码 ...

  5. (亲测)躺着破解IDM下载权限,治疗不用破解补丁的强迫症们

    首先.如果触犯了某些规则权限,请原谅. 很早以前就做过这个的破解,挺实用的,我今天就把之前写的经验贴出来大家一起学习学习~~~ 今天利用这个方法破解了最新版,最终的效果如下所示:我不是来刷存在感的.只 ...

  6. 【BZOJ5505】[GXOI/GZOI2019]逼死强迫症(矩阵快速幂)

    [BZOJ5505][GXOI/GZOI2019]逼死强迫症(矩阵快速幂) 题面 BZOJ 洛谷 题解 如果没有那两个\(1*1\)的东西,答案就是斐波那契数,可以简单的用\(dp\)得到. 大概是设 ...

  7. [LOJ3086][GXOI/GZOI2019]逼死强迫症——递推+矩阵乘法

    题目链接: [GXOI/GZOI2019]逼死强迫症 设$f[i][j]$表示前$i$列有$j$个$1*1$的格子的方案数,那么可以列出递推式子: $f[i][0]=f[i-1][0]+f[i-2][ ...

  8. P5303 [GXOI/GZOI2019]逼死强迫症

    题目地址:P5303 [GXOI/GZOI2019]逼死强迫症 这里是官方题解 初步分析 从题目和数据范围很容易看出来这是一个递推 + 矩阵快速幂,那么主要问题在于递推的过程. 满足条件的答案一定是以 ...

  9. [JZOJ4786]小a的强迫症

    [JZOJ4786]小a的强迫症 题目大意: 有\(n(n\le10^5)\)种颜色的珠子,第\(i\)种颜色有\(num[i]\)个.你要把这些珠子排成一排,使得第\(i\)种颜色的最后一个珠子一定 ...

随机推荐

  1. [转]How to: Execute Oracle Stored Procedures Returning RefCursors

    本文转自:http://www.telerik.com/help/openaccess-orm/openaccess-tasks-oracle-execute-sp-result-set.html I ...

  2. 关于SWT中的表格(TableViewer类)

    JFace是SWT的扩展.它提供了一组功能强大的界面组件.其中包含表格,树,列表.对话框,向导对话框等. 表格是一种在软件系统中很常用的数据表现形式.特别是基于数据库的应用系统.表格更是不可缺少的界面 ...

  3. 非XA式Spring分布式事务

    Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...

  4. mongodb添加权限

    1.连接mongodb数据库(如果mongo命令没有做环境变量配置,需要定位到有mongo命令的目录) root@AY140709212620347s22Z:~# mongo MongoDB shel ...

  5. ASP大数据量使用GetRows()提升速度

    抽取10万条数据,Access数据库,GetRows() 现有10W条数据,Access数据库保存 通过正常提取: <% Set conn= Server.CreateObject(" ...

  6. Android更改桌面应用程序launcher的两种方式

    http://blog.csdn.net/mdx20072419/article/details/9632779/ launcher,也就是android的桌面应用程序.下图是我正在使用的魅族手机的l ...

  7. C# lazy加载

    转自http://www.cnblogs.com/yunfeifei/p/3907726.html 在.NET4.0中,可以使用Lazy<T> 来实现对象的延迟初始化,从而优化系统的性能. ...

  8. sql的游标使用(转)

    游标是邪恶的! 在关系数据库中,我们对于查询的思考是面向集合的.而游标打破了这一规则,游标使得我们思考方式变为逐行进行.对于类C的开发人员来着,这样的思考方式会更加舒服. 正常面向集合的思维方式是: ...

  9. 二维树状数组——SuperBrother打鼹鼠(Vijos1512)

    树状数组(BIT)是一个查询和修改复杂度都为log(n)的数据结构,主要用于查询任意两位之间的所有元素之和,其编程简单,很容易被实现.而且可以很容易地扩展到二维.让我们来看一道很裸的二维树状数组题: ...

  10. 利用绝对定位与margin实现元素居中

    例: 要让一个width:100px ; height: 100px;的div,相对body居中. div{ width:100px; height:100px; border: 1px solid ...