USACO Training Section 2.1 Sorting a Three-Valued Sequence

[url="http://ace.delos.com/usacoprob2?a=1037lYCaha0&S=sort3"]英文原题[/url] [url="http://www.wzoi.org/usaco/12%5C510.asp"]中文题译[/url]
题目大意是:给定一个由数字123构成的数列,最少多少次交换可以使得其变成升序序列。

以前做过POJ上的USACO题中有类似的,大意是给定123的序列,不交换,但可改变数字的值,问至少要改变多少个值使得整个序列有序。比这个略难些。对此题,扫描整个数列,得到每个数字区间的位置,考虑到首先所有的在23区间的1必须交换回1区间,然后考虑这样的交换会导致多少3跑到区间2中。注意n_i_j中存在一些等式,所以计算不难。

可将此题推广,在长为N的序列中有M个数,最少多少交换可使得序列变成升序。这样,第一部分基本不变,需要N×M的数组来记录数字位置,如果N×M很大,则可以两次扫描,第一次扫描得到每个数字的位置,第二次扫描用M×M数组(M×(M-1)/2就够)存放错位情况即:数字j在区间i中出现的个数。然后M循环,首先把数字1放在区间1内,逐个更新余下的错位数,然后数字2,....。算法的时间复杂度为O(N*M+M^3),考虑到一般M<<N,故依然为O(N*M),不过编程复杂度集中在后部。


/*
ID: blackco3
TASK: sort3
LANG: C++
*/
#include <fstream>
using namespace std;
#define _max_ 1000
int main() {
ifstream fin("sort3.in");
ofstream fout("sort3.out");
int n_digit, n_dig[3]={0, 0, 0}, count[3][_max_+1]={{0}, {0}, {0}}, cur ;
fin >> n_digit ;
for( int i=1; i<=n_digit; i++ ){
fin >> cur ;
for( int j=0; j<3; j++){
count[j][i] = count[j][i-1] + (j==cur-1) ;
n_dig[j] += (j==cur-1) ;
}
}
int n21=count[1][n_dig[0]]; /* how many 2 in segment 1 */
int n31=count[2][n_dig[0]]; /* how many 3 in segment 1 */
int n12=count[0][n_dig[0]+n_dig[1]]-count[0][n_dig[0]]; /* how many 1 in segment 2 */
int n32=count[2][n_dig[0]+n_dig[1]]-count[2][n_dig[0]]; /* how many 3 in segment 2 */
fout << (n21 + n31) + (n32 + n12 - (n12<n21 ? n12 : n21)) << endl ;
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值