(一道Div2E不会,我太难了)

题意:

给你一个长度为$n$的颜色序列$A$,每次操作可以选择两个相邻元素交换,求把序列交换成“相同颜色挨在一起”所需的最少操作数。

按颜色排序:设颜色$col$在序列中出现的最左处为$l$,最右处为$r$,则$A_{l},\cdots , A_{r}=col$

$n\leq 4\times 10^5,A_{i}\leq 20$

题解:

根据那个20的范围我们可以考虑一个状压dp的做法。

一般人定义状态都是设$dp(s)$表示排好s中的颜色所需要的最少步数,转移时将其他颜色视为空位。

但这样发现还需要记录状态s的位置,才能计算答案。

这道题计算答案的方法比较巧妙,它的状态是$dp(s)$表示当这个序列中只有s中的颜色时将这个序列变得合法所需要的最少步数。

有什么区别?一个是将其他颜色视为空位,一个是直接抹除其他颜色以及它们所在的位置。

为什么要这样?假如在颜色i,j中间有颜色k,那么将j交换到i前面可以分成两种交换,一种是i与j的交换,一种是j与k的交换。

那么此时相当于只计算了前一种交换而忽略了后一种交换,看起来非常错误。

但注意到,若产生这样的情况,那么k在答案中必在i,j之前,此时一定有先将k换到前面再将j换到i前面更优。

也就是说,虽然这个做法在中间过程中答案大概率是错误的,但最终的答案却是正确的。

证明可以考虑从:

(1)得到的答案在原序列中一定可以做到;

(2)得到的答案一定不劣于正确答案;

这两点来证明。

那么我们预处理$cnt(i,j)$表示当序列中只有i,j两种颜色时,将颜色i交换到颜色j前面所需的最少步数。

画个图发现转移时累加的答案为$\sum {cnt(i,k)}$

并不难写,复杂度$O(400\times n)$

(我根本就没学明白dp)

代码:

#include<bits/stdc++.h>
#define maxn 400005
#define maxm 25
#define inf 0x7fffffff
#define ll long long using namespace std;
int N,M,A[maxn];
ll dp[<<maxm-],cnt[maxm][maxm]; //cnt[i][j]:put i infront j
queue<int> q; bool vis[maxm]; inline int read(){
int x=,f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
} int main(){
N=read(),M=;
for(int i=;i<=N;i++) A[i]=read();
for(int x=;x<=M;x++)
for(int y=;y<=M;y++){
while(!q.empty()) q.pop();
for(int i=;i<=N;i++){
if(A[i]==x){
if(q.empty()) continue;
int u=q.front();
cnt[x][y]+=(ll)q.size();
q.pop(),q.push(i);
}
else if(A[i]==y) q.push(i);
else continue;
}
}
memset(dp,,sizeof(dp));
dp[]=;
for(int s=;s<(<<M);s++){
memset(vis,,sizeof(vis));
for(int i=;i<=M;i++){
if(s&(<<i-)) vis[i]=;
else vis[i]=;
}
for(int i=;i<=M;i++){
if(s&(<<i-)) continue;
ll ans=;
for(int j=;j<=M;j++)
if(vis[j]) ans+=cnt[i][j];
dp[s|(<<i-)]=min(dp[s|(<<i-)],dp[s]+ans);
}
}
printf("%I64d\n",dp[(<<M)-]);
return ;
}

Marbles

[cf 585 E] Marbles的更多相关文章

  1. CF 585 E Present for Vitalik the Philatelist

    CF 585 E Present for Vitalik the Philatelist 我们假设 $ f(x) $ 表示与 $ x $ 互质的数的个数,$ s(x) $ 为 gcd 为 $ x $ ...

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

    题目:https://codeforc.es/contest/1215/problem/E 题意:给你一个序列,你可以交换相邻的两个数,要达到一个要求,所有相同的数都相邻,问你交换次数最少是多少 思路 ...

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

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

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

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

  5. Codeforces Round 585

    Codeforces Round 585 浅论如何发现自己是傻子的-- 反正今天是完全蒙的,水了签到题就跑了-- A. Yellow Cards 签到题. 众所周知,CF的签到题一般是一道神神奇奇的数 ...

  6. ORA-00494: enqueue [CF] held for too long (more than 900 seconds) by 'inst 1, osid 5166'

    凌晨收到同事电话,反馈应用程序访问Oracle数据库时报错,当时现场现象确认: 1. 应用程序访问不了数据库,使用SQL Developer测试发现访问不了数据库.报ORA-12570 TNS:pac ...

  7. cf之路,1,Codeforces Round #345 (Div. 2)

     cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....   ...

  8. cf Round 607

    A.Chain Reaction(DP+二分) 题意:一排有n个灯塔,每个灯塔给出坐标xi和力量yi,每次从最右边依次点亮灯塔,每点亮一个灯塔,它左边的距离它yi范围内的灯塔将受到损坏.现在允许在最右 ...

  9. cf Round 613

    A.Peter and Snow Blower(计算几何) 给定一个点和一个多边形,求出这个多边形绕这个点旋转一圈后形成的面积.保证这个点不在多边形内. 画个图能明白 这个图形是一个圆环,那么就是这个 ...

随机推荐

  1. linux实现pwd

    版本1: 调用系统接口getcwd,实现路径打印. /*** ***文件名:1_mypwd.c ***描述:通过系统函数getcwd实现pwd命令 ***/ #include<stdio.h&g ...

  2. GoCN每日新闻(2019-10-27)

    GoCN每日新闻(2019-10-27) 1. Golab(意大利GopherCon)2019见闻 http://fedepaol.github.io/blog/2019/10/23/golab-20 ...

  3. nginx之allow、deny

    allow和deny这两个指令的意思是指,允许ip和限制ip 在此之前不得不提一下,这两个指令是存在于ngx_http_access_module模块之中的 allow语法:allow address ...

  4. ruby-on-rails-BUG

    Ruby on Rails errors: (新手期) rails 自动化部署教程 Q1: rvm 无法使用 $ rvm use 1.9.3 --default RVM is not a functi ...

  5. 【C++】C++中的异常解析

    异常是程序在执行期间产生的问题.C++ 异常是指在程序运行时发生的特殊情况,比如尝试除以零的操作. 异常提供了一种转移程序控制权的方式.C++ 异常处理涉及到三个关键字:try.catch.throw ...

  6. Parquet介绍及简单使用(转)

    ==> 什么是parquet         Parquet 是列式存储的一种文件类型   ==> 官网描述: Apache Parquet is a columnar storage f ...

  7. 登陆服务器提示“You need to run "nvm install N/A" to install it before using it.”

    一.登陆服务器提示“You need to run "nvm install N/A" to install it before using it.” 二.执行命令: nvm ls ...

  8. 查找算法(2)--Binary chop--二分查找

    1. 二分查找 (1)说明 元素必须是有序的,如果是无序的则要先进行排序操作. (2)基本思想: 也称为是折半查找,属于有序查找算法.用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表, ...

  9. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器功能简介---视频直播、直播鉴权(如何完美将EasyDSS过渡到新版)

    作为RTMP流媒体服务器,接受RTMP推流.进行实时的直播流分发是EasyDSS流媒体服务自身一大核心功能.写本篇博文的一个目的是向大家介绍EasyDSS新版的直播间.匿名直播.和虚拟直播的功能, 另 ...

  10. LeetCode_461. Hamming Distance

    461. Hamming Distance Easy The Hamming distance between two integers is the number of positions at w ...