[cf 585 E] Marbles
(一道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的更多相关文章
- CF 585 E Present for Vitalik the Philatelist
CF 585 E Present for Vitalik the Philatelist 我们假设 $ f(x) $ 表示与 $ x $ 互质的数的个数,$ s(x) $ 为 gcd 为 $ x $ ...
- Codeforces Round #585 (Div. 2) E. Marbles (状压DP)
题目:https://codeforc.es/contest/1215/problem/E 题意:给你一个序列,你可以交换相邻的两个数,要达到一个要求,所有相同的数都相邻,问你交换次数最少是多少 思路 ...
- Codeforces Round #585 (Div. 2) E. Marbles(状压dp)
题意:给你一个长度为n的序列 问你需要多少次两两交换 可以让相同的数字在一个区间段 思路:我们可以预处理一个数组cnt[i][j]表示把i放到j前面需要交换多少次 然后二进制枚举后 每次选择一个为1的 ...
- Codeforces Round #585 (Div. 2) E. Marbles (状压DP),BZOJ大理石(同一道题)题解
题意 林老师是一位大理石收藏家,他在家里收藏了n块各种颜色的大理石,第i块大理石的颜色为ai.但是林老师觉得这些石头在家里随意摆放太过凌乱,他希望把所有颜色相同的石头放在一起.换句话说,林老师需要对现 ...
- Codeforces Round 585
Codeforces Round 585 浅论如何发现自己是傻子的-- 反正今天是完全蒙的,水了签到题就跑了-- A. Yellow Cards 签到题. 众所周知,CF的签到题一般是一道神神奇奇的数 ...
- 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 ...
- cf之路,1,Codeforces Round #345 (Div. 2)
cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅..... ...
- cf Round 607
A.Chain Reaction(DP+二分) 题意:一排有n个灯塔,每个灯塔给出坐标xi和力量yi,每次从最右边依次点亮灯塔,每点亮一个灯塔,它左边的距离它yi范围内的灯塔将受到损坏.现在允许在最右 ...
- cf Round 613
A.Peter and Snow Blower(计算几何) 给定一个点和一个多边形,求出这个多边形绕这个点旋转一圈后形成的面积.保证这个点不在多边形内. 画个图能明白 这个图形是一个圆环,那么就是这个 ...
随机推荐
- yarn和npm的对比,以及项目中使用方式
相比npm 的优点 1.npm安装是串行,而yarn是并行,速度大大提升 2.已经下载过的包会被缓存,无需重复下载,更关键的是,支持离线安装 3.精准的版本控制,加上验证每个包的完整性,保证每次安装的 ...
- MySQL中自增ID起始值修改方法
在实际测试工作过程中,有时因为生产环境已有历史数据原因,需要测试环境数据id从某个值开始递增,此时,我们需要修改数据库中自增ID起始值,下面以MySQL为例: 表名:users; 建表时添加: ); ...
- 对IT战略的认识
提到战略,我不由想起了战术这个名词.按照我的理解,战术属于短期内的计划,是战略的组成部分,是实施次战略的短期工作计划或行动步骤:而战略是用来帮助我们赢取目标的行动计划(例如为获得更多的潜在客户而制定的 ...
- 南开大学2020年数学分析高等代数考研试题回忆版TeX排版
南开大学2020年数学分析高等代数考研试题回忆版TeX排版 220328[南开大学2020年高等代数考研试题回忆版] 220329[南开大学2020年数学分析考研试题回忆版]
- List和数组的互转
list转数组: /要转换的list集合 List<String> testList = new ArrayList<String>(){{add("aa" ...
- JPA的动态查询拼接
在使用Spring JPA提供的方法只能进行简单的CRUD,如果遇到复杂的情况就需要我们动态来构建查询条件了.这里我们来看使用CriteriaBuilder如何来构造查询.核心代码: Criteria ...
- LiteIDE 设置默认编译输出位置
go build命令默认输出路径是当前工作路径,这个显得比较乱,我习惯于把输出文件放置在项目的build目录下,这样方便查找,已经同步备份的时候排除不必要的文件. go build命令可以指定-o 输 ...
- OkHttp3 readError问题解决
有些时候是服务端响应的太慢而本地链接又关闭引起的读取失败. 这时候可以调整本地链接关闭的时间. 例如以下设置超时关闭的时间为120秒. OkHttpClient okHttpClient = new ...
- 如何防止Hangfire重复作业在连续执行30分钟后重新启动(How to prevent a Hangfire recurring job from restarting after 30 minutes of continuous execution)
var options = new SqlServerStorageOptions { InvisibilityTimeout = TimeSpan .FromMinutes(30)//默认值}; G ...
- 面试突击(八)——JVM的结构及内存模型,是怎么划分的?
声明:本文图片均来自网络,我只是进行了选择,利用一图胜千言的力量来帮助自己快速的回忆相关的知识点 0:再上一张Java代码的转换流程图 .java——Java程序员编写,给人看的 .class——Ja ...