1164: 分治 逆序对
时间限制: 1 Sec
内存限制: 128 MB
题目描述
给一列数a1,a2,...,an,求它的逆序对数,即有多少个有序对(i,j),使得i<j且ai>aj。n可以高达10^6。
输入
第一行输入整数N(2<=N<=10^6).
接下来一行N个正整数数分别是a1,a2,...,an(ai<=10^6)。
输出
样例输入
4
2 4 3 1
样例输出
4
重点体会分治思想!!
要熟练会写,有一道叫做手套的题就考了逆序对,一会贴上。
这里直接粘代码了
- #include<iostream>
- #include<cstdio>
- using namespace std;
- int n,a[2000001],i,c[2000001];
- long long ans;
- void x(int l,int r)
- {
- int mid=(l+r)/2,i,j,tmp;
- if(r>l)
- {
- x(l,mid);
- x(mid+1,r);
- tmp=l;
- for(i=l,j=mid+1;i<=mid&&j<=r;)
- {
- if(a[i]>a[j])
- {
- c[tmp++]=a[j++];
- ans+=mid-i+1;
- }
- else c[tmp++]=a[i++];
- }
- if(i<=mid) for(;i<=mid;) c[tmp++]=a[i++];
- if(j<=r) for(;j<=r;) c[tmp++]=a[j++];
- for(i=l;i<=r;i++) a[i]=c[i];
- }
- }
- int main()
- {
- cin>>n;
- for(i=1;i<=n;i++) scanf("%d",&a[i]);
- x(1,n);
- cout<<ans;
- }
还有一份
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- using namespace std;
- int A[9000010]={0},T[9000010]={0};
- long long cnt=0;
- void merge_sort(int x,int y)
- {
- if(y-x>=1){
- int m=(y-x)/2+x;
- int p=x,q=m+1,i=x;
- merge_sort(x,m);
- merge_sort(m+1,y);
- while(p<=m||q<=y){
- if(q>y||(p<=m&&A[p]<=A[q]))T[i++]=A[p++];
- else {T[i++]=A[q++];cnt+=m+1-p;}
- }
- for(i=x;i<=y;i++)A[i]=T[i];
- }
-
- }
- int main()
- {
- int n,m,ans=0,i,k;
- scanf("%d",&n);
- for(i=0;i<n;i++)
- {
- scanf("%d",&A[i]);
-
- }
- merge_sort(0,n-1);
- printf("%lld",cnt);
-
- }