poj2299UltraQuickSort

http://poj.org/problem?id=2299

求逆序数

第一种做法 利用归并排序 在进行两个升序数组归并时 如果右边指针指向的那个数比左边小 那从左边那个位置到mid的数都比右边那个数大 所以比它大的数的个数就是 左边那个数到mid之间的数 依次类推

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 long long a[500001],num,x[500001],y[500001];
 4 long long  msort(long long low,long long mid,long long high)
 5  {
 6      long long  i,j,n1 = mid-low+1,n2 = high-mid;
 7      for(i = 1 ; i <= n1 ; i++)
 8          x[i] = a[low+i-1];
 9      for(i = 1 ; i <= n2 ; i++)
10          y[i] = a[mid+i];
11      long long k = low;
12      i = 1;
13      j = 1;
14      while(i<=n1&&j<=n2)
15      {
16          if(x[i]<=y[j])
17              a[k] = x[i++];
18          else
19          {
20              num+=mid-(low+i)+2;//加上i到mid之间的数
21              a[k] = y[j++];
22          }
23          k++;
24      }
25      while(i<=n1)
26          a[k++] = x[i++];
27      while(j<=n2)
28          a[k++] = y[j++];
29  }
30  void merge(long long low,long long high)
31  {
32      long long  mid;
33      if(low<high)
34      {
35          mid = (low+high)/2;
36          merge(low,mid);
37          merge(mid+1,high);
38          msort(low,mid ,high);
39      }
40  }
41 int main()
42 {
43     int i,j,k,n,m;
44     while(scanf("%d",&n)&&n)
45     {
46         num = 0;
47         for(i = 1; i <= n ; i++)
48         scanf("%d",&a[i]);
49         merge(1,n);
50         printf("%lld\n",num) ;
51     }
52     return 0;
53 }

 第二种 树状数组

树状数组时用来求和的 从小到大排好序之后 用一个数组记录原来位置的数现在在什么位置 然后调用更新函数 让原来那个位置标记为1 这样再调用getsum函数 就可以得到原来这个位置前面有多少比它小的数 依次加起来

View Code
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef struct node
 7 {
 8     int a,p;
 9 }st;
10 st q[500001];
11 int re[500001],n,po[500001];
12 bool cmpp(st x, st y)
13 {
14     return x.a<y.a;
15 }
16 void add(int i,int da)
17 {
18     while(i<=n)
19     {
20        re[i]+=da;
21        i += i&(-i);
22     }
23 }
24 int getsum(int i)
25 {
26     long long s = 0;
27     while(i)
28     {
29         s+=re[i];
30         i-=i&(-i);
31     }
32     return s;
33 }
34 int main()
35 {
36     int i,j,m;
37     long long s1;
38     while(scanf("%d",&n)&&n)
39     {
40         s1 = 0;
41         memset(re,0,sizeof(re));
42         for(i = 1 ; i <= n ; i++)
43         {
44             scanf("%d",&q[i].a);
45             q[i].p = i;
46         }
47         sort(q+1,q+n+1,cmpp);
48         for(i = 1 ; i <= n ; i++)
49             po[q[i].p] = i;
50         for(i = 1 ; i <= n ; i++)
51         {
52             add(po[i],1);
53             s1+=(i-getsum(po[i]));
54         }
55         printf("%lld\n",s1);
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/shangyu/p/2613033.html