排序
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
小a有一个DNA序列串,强迫症的小a看它不顺眼,想将它排好序。
给定长为n的DNA序列串s(仅由`A,T,G,C`最多四种字符构成)。你可以进行任意次如下操作:任选两个位置i,j(i<j),交换这两个字符si,sj,花费为2×(j−i)−1(即:将si不断与si+1交换,直到移动到j位置,再将sj不断与sj−1交换,直到移动到i位置所需的总移动次数)。求将序列串中同种字符划分到一起的最小花费(如字符串`AGACG`,将其变成`AAGGC`或`GGAAC`或`CAAGG`...都是合法的,最小花费是2:`AAGGC`)。
输入描述:
输入一行,一个字符串s,表示题目描述所述的DNA序列串。
输出描述:
输出一个整数,表示将s中同种字符划分到一起的最小花费。
示例1
输入
AGACG
输出
2
备注:
字符串长度n满足1≤n≤2×105。
链接:https://ac.nowcoder.com/acm/contest/1842/C
题意:相邻之间交换,最终形式是相同字符挨在一起,求最小花费。
题解:归并排序+全排列(四个字符不同价值全排列)
样例卡longlong!!
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+5;
int a[maxn]; //原始数组
int temp[maxn]; //维护
long long cnt=0; //答案
void Msort(int l,int r){
int mid=(l+r)/2;
if(r>l){
Msort(l,mid);
Msort(mid+1,r);
int op=l,i=l,j=mid+1;
while(i<=mid&&j<=r)
{
if(a[i]>a[j])
{
temp[op++]=a[j++];
cnt+=mid-i+1;
}else
temp[op++]=a[i++];
}
if(i<=mid) for(;i<=mid;) temp[op++]=a[i++];
if(j<=r) for(;j<=r;) temp[op++]=a[j++];
for(i=l;i<=r;i++) a[i]=temp[i];
}
}
int book[5];
int shunxu[5];
long long mincnt;
string s;
void dfs(int n)
{
if(n>4)
{
cnt=0;
for(int i=0;i<s.length(); i++)
{
if(s[i]=='A')
a[i]=shunxu[1];
else if(s[i]=='T')
a[i]=shunxu[2];
else if(s[i]=='C')
a[i]=shunxu[3];
else if(s[i]=='G')
a[i]=shunxu[4];
}
Msort(0,s.length()-1);
mincnt=min(mincnt,cnt);
return;
}
for(int i=1;i<=4;i++)
{
if(book[i]==0)
{
book[i]=1;
shunxu[n]=i;
dfs(n+1);
book[i]=0;
}
}
}
int main(){
cin>>s;
mincnt=1e18;
dfs(1);
cout<<mincnt<<endl;
return 0;
}