[CF1526D] Kill Anton(逆序对,搜索)
题面
A
N
T
O
N
\rm ANTON
ANTON 的基因由
A
,
N
,
T
,
O
\rm A,N,T,O
A,N,T,O 四种碱基排列组成。
A
N
T
O
N
\rm ANTON
ANTON 的身体很智能,一旦发现基因序列被改变了,就会通过尽量少的次数交换相邻两个碱基,来还原回开始的基因序列。
现在给出
A
N
T
O
N
\rm ANTON
ANTON 的基因序列,长为
N
N
N ,求一个打乱后的该序列,满足还原时需要交换操作最少次数最多,输出任意一个符合条件的序列。
1
≤
N
≤
1
0
5
1\leq N \leq10^5
1≤N≤105.
题解
我们先考虑最少操作次数怎么求。根据做题经验,有一个贪心思路:把相同类型的碱基不交叉地一一配对,然后把每个初始位置的目标位置拿出来组成一个序列(因此这应该是个1~N的排列),最小操作次数即该排列的逆序对数。
那么,我们不妨把打乱后的序列也这样一一对应回去,每个位置上记录初始位置的编号。容易发现,对于同一种碱基的所有位置,初始位置的编号一定是单增的。在满足这个条件的情况下,我们可以想想怎么最大化逆序对数。
这里有一个结论:一定存在一种逆序对最多的方案,满足同种碱基都相邻。
- 证明:我们用调整法,假设序列中有这么一段两边都有个 A(省略号中间没有 A):
A......A,前面一个的初始位置为i
i
i ,后面一个的初始位置为
j
j
j,此时
i
<
j
i<j
i<j。令省略号中间比
i
i
i 小的数量为
a
a
a ,比
j
j
j 大的数量为
b
b
b 。如果
a
≥
b
a\geq b
a≥b,把右边的 A 移到省略号左边,逆序对的变化量为
a
−
b
≥
0
a-b\geq0
a−b≥0 。如果
a
<
b
a<b
a<b ,把左边的 A 移到省略号右边,逆序对的变化量为
b
−
a
>
0
b-a>0
b−a>0。两种使 A 相邻的方法总有一个不会让逆序对数减小,得证。
那么,由于只有四种碱基,全排列有
M
!
=
4
!
=
24
M!=4!=24
M!=4!=24 种,最终的序列也只有这么多种,其中一定存在一个答案序列,我们暴力枚举找它。复杂度
O
(
M
!
n
log
n
)
O(M!n\log n)
O(M!nlogn)。
还有一种
O
(
n
)
O(n)
O(n) 的做法。交换次数不一定要求逆序对,还可以求初始与目标的距离。由于我们知道同种碱基要相邻,可以通过预处理前缀和等方式,快速判断每种碱基段在某个位置对答案贡献为多少,这样一来,枚举全排列时就不用每次
O
(
n
)
O(n)
O(n) 求答案,而是常数时间。总时间复杂度就主要只有输入和预处理了。
CODE
O
(
24
n
log
n
)
O(24n\log n)
O(24nlogn)
#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 400005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
#define INF 0x3f3f3f3f
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
char s0[10] = "ANTO";
char ss[MAXN];
int c[MAXN];
void addc(int x,int y){while(x<=n)c[x]+=y,x+=lowbit(x);}
int sum(int x){int s=0;while(x>0)s+=c[x],x-=lowbit(x);return s;}
void INIT() {for(int i = 1;i <= n;i ++) c[i] = 0;}
LL as = 0,CN;
char D[MAXN],e[MAXN];
void ADD(int x) {
D[CN --] = ss[x];
as += sum(x-1); addc(x,1);
return ;
}
int main() {
int T = read();
while(T --) {
scanf("%s",ss + 1);
n = strlen(ss + 1);
for(int i = 1;i <= n;i ++) e[i] = ss[i];
LL ans = -1;
for(int a=0;a<4;a++) {
for(int b=0;b<4;b++) if(b!=a) {
for(int c=0;c<4;c++) if(c!=a&&c!=b) {
for(int d=0;d<4;d++) if(d!=a&&d!=b&&d!=c) {
INIT();
CN = n;as = 0;
for(int i = n;i > 0;i --) if(ss[i] == s0[d]) ADD(i);
for(int i = n;i > 0;i --) if(ss[i] == s0[c]) ADD(i);
for(int i = n;i > 0;i --) if(ss[i] == s0[b]) ADD(i);
for(int i = n;i > 0;i --) if(ss[i] == s0[a]) ADD(i);
if(as > ans) {
for(int i = 1;i <= n;i ++) e[i] = D[i];
ans = as;
}
}
}
}
}
for(int i = 1;i <= n;i ++) putchar(e[i]);ENDL;
}
return 0;
}
[CF1526D] Kill Anton(逆序对,搜索)的更多相关文章
- 剑指Offer(三十五):数组中的逆序对
剑指Offer(三十五):数组中的逆序对 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/bai ...
- Codeforces Round #329 (Div. 2) B. Anton and Lines 逆序对
B. Anton and Lines Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/593/pr ...
- CF785CAnton and Permutation(分块 动态逆序对)
Anton likes permutations, especially he likes to permute their elements. Note that a permutation of ...
- 洛谷 P1521 求逆序对
题目描述 我们说(i,j)是a1,a2,…,aN的一个逆序对当且仅当i<j且ai>a j.例如2,4,1,3,5的逆序对有3个,分别为(1,3),(2,3),(2,4).现在已知N和K,求 ...
- leetcode_315_逆序对问题
题目描述 本题来自于Leetcode的算法题库第315题,具体题目描述如下: 给定一个nums整数数组 ,按要求返回一个counts新数组 .数组 counts 有该性质: counts[i]的值是 ...
- 【CQOI2011】动态逆序对 BZOJ3295
Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...
- CH Round #72 奇数码问题[逆序对 观察]
描述 你一定玩过八数码游戏,它实际上是在一个3*3的网格中进行的,1个空格和1~8这8个数字恰好不重不漏地分布在这3*3的网格中. 例如:5 2 81 3 _4 6 7 在游戏过程中,可以把空格与其上 ...
- POJ3928Ping pong[树状数组 仿逆序对]
Ping pong Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3109 Accepted: 1148 Descrip ...
- NOIP2013火柴排队[逆序对]
题目描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示 ...
随机推荐
- numpy中shape的部分解释
转载自:https://blog.csdn.net/qq_28618765/article/details/78081959和https://www.jianshu.com/p/e083512e4f4 ...
- GDKOI 2021 Day2 PJ 去世记
比赛时和昨天一样困,后面的大奆打代码的速度简直了 T1 用 2.4.6.8 来与 5 抵消掉末尾的 0 ,然后用周期问题的方法直接乘起来并取个位 #include<bits/stdc++.h&g ...
- DevOps落地实践点滴和踩坑记录-(1)
记录初衷 本人一直在从事企业内DevOps落地实践的工作,走了不少弯路,也努力在想办法解决面临的问题,期间也经历过不少人和事情,最近突然有想法把经历过的,不管好的不好的都记录下来,分享给和我一样的一线 ...
- ExtJS 布局-HBox 布局(HBox layout)
更新记录: 2022年6月11日 更新文章结构. 2022年6月8日 发布. 2022年6月1日 开始. 1.说明 hbox布局与column布局几乎相同,但hbox允许拉伸列的高度. 既可以在水平方 ...
- 建立QT工程的规范型,以及重要性
当前管理开发多个项目,故名Projects 下一级目录,具体项目,故示例Project,根据实际情况自行取名 再下一级目录,有三个子目录 bin:生成的可执行文件或者动态链接库,build:编译源码时 ...
- 如何通过WinDbg获取方法参数值
引入 我们在调试的过程中,经常会通过查看方法的输入与输出来确定这个方法是否异常.那么我们要怎么通过 WinDbg 来获取方法的参数值呢? WinDbg 中主要包含三种命令:标准命令.元命令(以 . 开 ...
- 在linux上配置Maven环境变量
1.首先下载maven ,这里我使用的是3.8.1 Maven – Download Apache Maven 2.在linux环境中,将maven上传至 /usr/local/目录中 这里我将mav ...
- 【docker专栏1】docker解决的实际问题及应用场景
Docker是一个开源的容器引擎,它轻巧,且易移植,"build once, configure once and run anywhere".使用go语言开发,并遵从apache ...
- 微信开发在Pc端调用公众号粉丝发送过来的图片素材
因为项目要在PC端搞一个微信墙功能,就是把粉丝发送过来的上墙内容给展示出来,但因为微信对微信素材进行了防盗链加密处理,所以在非微信页面上直接引用在微信服务器上的图片的链接是无法显示的,只会显示一张微信 ...
- Java开发学习(十一)----基于注解开发bean作用范围与生命周期管理
一.注解开发bean作用范围与生命周期管理 前面使用注解已经完成了bean的管理,接下来将通过配置实现的内容都换成对应的注解实现,包含两部分内容:bean作用范围和bean生命周期. 1.1 环境准备 ...