题意 : 给出一个数n(n<500,000), 再给出n个数的序列 a1、a2.....an每一个ai的范围是 0~999,999,999 要求出当通过相邻两项交换的方法进行升序排序时需要交换的次数
分析:其实经过一次模拟后,会发现奇妙的东西,这个排序都是按位置排的,最大要求到最大,最小要去到最小,转化思想这是一道求逆序对数的题目,答案就是逆序对数。
这里数据过大999999999,数组无法开的了这么大,我们可以离散化,只记录相对大小。
这里离散化有所不同,这里为了压时,用了空间换时间的方法. 前面的文章有讲到sum(i)表示前面有多少比这个小的数,可以sum(n)-sum(i), 这里有新知识就是sum(i)表示有多少小的数,那当前的总数是i,那大的数就是(i-sum(i)这也是求逆序对的方法,目测挺快的。
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; int a[100]; int b[100],c[100],n; int lowbit(int x) { return x&(-x); } void add(int k,int num) { while(k<=n) { c[k]+=num; k+=lowbit(k); } } int sum(int k) { int ans=0; while(k) { ans+=c[k]; k-=lowbit(k); } return ans; } int main( ) { while(scanf("%d",&n)!=EOF) { memset(c,0,sizeof(c)); if(n==0) break; for(int i=0 ; i<n ; i++) { scanf("%d",&a[i]); b[i]=a[i]; } sort(b,b+n); int summ=0; for(int i=0 ; i<n ; i++) { a[i] = (lower_bound(b,b+n,a[i])-b)+1; summ+=(sum(n)-sum(a[i])); //summ+=(i-sum(a[i]+1) add(a[i],1); } printf("%d\n",summ); } }
原文地址:https://www.cnblogs.com/shuaihui520/p/9119706.html
时间: 2024-10-11 23:31:10