转载注明出处: http://blog.csdn.net/u011400953
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 36281 | Accepted: 13078 |
Description
Input
Output
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
Source
【题目大意】:
求对于一数列冒泡的交换次数
【分析】:
转化题目模型:求序列的逆序对数
逆序对数:设A[1..n]是一个包含N个非负整数的数组。如果在i<j的情况下,有A[i]>A[j],则(i,j)就称为A中的一个逆序对。例如,数组(3,1,4,5,2)的“逆序对”有<3,1>,<3,2><4,2><5,2>,共4个。定义:对于一个给定的数列,如果有i<j,且Ai>Aj,则称(i,j)为一逆序对. 要解决的问题是,给出一个数列,求出这个数列包含多少个逆序对
暂时了解到的有三种方法:归并排序,树状数组和权值线段树,代码给出前两种方法
【代码1,归并排序】:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<iostream> #include<vector> #include<stack> #include<queue> using namespace std; #define MAXN 500001 int N,a[MAXN],t[MAXN]; long long ans=0; void merge(int left,int mid,int right) { int now=0,l=left,r=mid+1; while(l<=mid && r<=right) { if(a[l]>a[r]) { t[now++]=a[r++]; ans+=mid-l+1; } else t[now++]=a[l++]; } while(l<=mid) t[now++]=a[l++]; while(r<=right) t[now++]=a[r++]; for(int i=0;i<now;i++) a[left+i]=t[i]; } void mergesort(int left,int right) { if(left<right) { int middle=(left+right)/2; mergesort(left,middle); mergesort(middle+1,right); merge(left,middle,right); } } int main() { //freopen("input.in","r",stdin); //freopen("output.out","w",stdout); while(scanf("%d",&N)!=EOF && N!=0) { ans=0; for(int i=1;i<=N;i++) scanf("%d",&a[i]); mergesort(1,N); /*for(int i=1;i<=N;i++) printf("%d ",a[i]); printf("\n");*/ printf("%I64d\n",ans); } //system("pause"); return 0; }
【代码2,树状数组】:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<iostream> #include<vector> #include<stack> #include<queue> using namespace std; #define MAXN 500001 struct DATA{int old,num,v;}; DATA a[MAXN]; int N,kind=0,old[MAXN]; long long S[MAXN],ans=0; bool cmp(DATA X,DATA Y){return X.old<Y.old;} bool cmp1(DATA X,DATA Y){return X.num<Y.num;} int lowbit(int x){return x&(-x);} void add(int x,int value) { int now=x; while(now<=kind) { S[now]+=value; now+=lowbit(now); } } long long getsum(int x) { int now=x; long long tmp=0; while(now>0) { tmp+=S[now]; now-=lowbit(now); } return tmp; } int main() { //freopen("input.in","r",stdin); //freopen("output.out","w",stdout); while(scanf("%d",&N)!=EOF && N!=0) { memset(S,0,sizeof(S)); ans=0; kind=0; for(int i=1;i<=N;i++) { scanf("%d",&a[i].old); a[i].num=i; } sort(a+1,a+1+N,cmp); int last=-1; for(int i=1;i<=N;i++) { if(a[i].old!=last) { last=a[i].old; a[i].v=++kind; } else a[i].v=kind; } sort(a+1,a+1+N,cmp1); for(int i=N;i>=1;i--) { ans+=getsum(a[i].v); add(a[i].v+1,1); } printf("%I64d\n",ans); } //system("pause"); return 0; }