牛客练习赛54 C题 排序

本文探讨了一种解决DNA序列排序问题的方法,通过计算逆序对数量来确定排序成本。介绍了如何使用Fenwick Tree(Binary Indexed Tree)进行高效计算,以及通过枚举所有可能的字符组合来找到最小花费。

排序

题目描述
小a有一个DNA序列串,强迫症的小a看它不顺眼,想将它排好序。
给定长为n的DNA序列串s(仅由A,T,G,C最多四种字符构成)。你可以进行任意次如下操作:任选两个位置i,j(i\lt ji<j),交换这两个字符s_i,s_js i,s​ ,花费为2\times(j-i)-12×(j−i)−1(即:将s_is i
不断与s_{i+1}s i+1 交换,直到移动到j位置,再将s_js j 不断与s_{j-1}s j−1
交换,直到移动到i位置所需的总移动次数)。求将序列串中同种字符划分到一起的最小花费(如字符串AGACG,将其变成AAGGCGGAACCAAGG…都是合法的,最小花费是2:AAGGC)。

输入描述:

输入一行,一个字符串s,表示题目描述所述的DNA序列串。

输出描述:

输出一个整数,表示将s中同种字符划分到一起的最小花费。


这道题的解法比较多,这里介绍一种求逆序对的做法;

分析题目我们会发现,求交换的最小花费就是求这个序列里面的逆序对数量,我们只要枚举24种情况产生的不同序列的最少逆序对数量就行;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
#define inf 0x3f3f3f3f
//ios::sync_with_stdio(false);
using namespace std;
const int N=200100;
const int M=200100;
const LL mod=998244353;
int n;
int tr[N];
string s;
int lowbit(int k){
	return k&(-k);
} 
void add(int p,int q){
	while(p<=n){
		tr[p]+=q;
		p+=lowbit(p);
	}
}
LL sum(int p){
	LL s=0;
	while(p){
		s=s+(LL)tr[p];
		p-=lowbit(p);
	}
	return s;
}
int f[N];
char h[4]={'A','T','C','G'};
LL change(int a,int b,int c,int d){
	memset(tr,0,sizeof(tr));
	for(int i=0;i<n;i++){
		if(s[i]==h[a]){
			f[i+1]=1;
			continue;
		}
		if(s[i]==h[b]){
			f[i+1]=2;
			continue;
		}
		if(s[i]==h[c]){
			f[i+1]=3;
			continue;
		}
		if(s[i]==h[d]){
			f[i+1]=4;
			continue;
		}
		return 2e17;
	}
	LL ss=0;
	for(int i=1;i<=n;i++){
		ss=ss+(LL)i-1LL-sum(f[i]);
		add(f[i],1);
	}
	return ss;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>s;
	n=s.length();
	LL mn=2e17;
	for(int i=0;i<4;i++){
		for(int j=0;j<4;j++){
			if(i==j) continue;
			for(int k=0;k<4;k++){
				if(j==k) continue;
				for(int l=0;l<4;l++){
					if(l==k) continue;
					mn=min(mn,change(i,j,k,l));
				}
			}
		}
	}
	cout<<mn<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值