逆序对
n(1<=n<=100000)个数,输出其中逆序对的对数。
输入:
5
2 3 1 5 4
输出:
3
离散化+树状数组
代码:
1 #include <bits/stdc++.h> 2 const int MAXN=1000; 3 using namespace std; 4 5 struct node{ 6 long long v; 7 int id; 8 bool operator <(const node&p) const{ 9 return v<p.v; 10 } 11 }; 12 node a[MAXN+10]; 13 long long c[MAXN+10]; 14 long long b[MAXN+10]; 15 int n; 16 17 inline int lowbit(int x){ 18 return x&-x; 19 } 20 21 long long Query(int x){ 22 long long ans=0; 23 while(x){ 24 ans+=c[x]; 25 x-=lowbit(x); 26 } 27 return ans; 28 } 29 30 void Change(int x){ 31 while(x<=n){ 32 c[x]++; 33 x+=lowbit(x); 34 } 35 } 36 37 void printA(){ 38 cout<<"a数组"<<endl; 39 cout<<setw(7)<<"id:"<<" "; 40 for(int i=1;i<=n;i++){ 41 cout<<a[i].id<<" "; 42 } 43 cout<<endl; 44 cout<<setw(7)<<"value:"<<" "; 45 for(int i=1;i<=n;i++){ 46 cout<<a[i].v<<" "; 47 } 48 cout<<endl; 49 } 50 51 void printB(){ 52 cout<<"b数组"<<endl; 53 cout<<setw(7)<<"b[i]:"<<" "; 54 for(int i=1;i<=n;i++){ 55 cout<<b[i]<<" "; 56 } 57 cout<<endl; 58 } 59 60 void printC(){ 61 cout<<"c数组"<<endl; 62 cout<<setw(7)<<"c[i]:"<<" "; 63 for(int i=1;i<=n;i++){ 64 cout<<c[i]<<" "; 65 } 66 cout<<endl; 67 } 68 69 int main(){ 70 freopen("in.txt","r",stdin); 71 freopen("out.txt","w",stdout); 72 cin>>n; 73 memset(a,0,sizeof(a)); 74 memset(b,0,sizeof(b)); 75 memset(c,0,sizeof(c)); 76 //离散化 77 for(int i=1;i<=n;i++){ 78 cin>>a[i].v; 79 a[i].id=i; 80 } 81 printA(); 82 sort(a+1,a+n+1); 83 cout<<endl<<"-----------------排序后-----------------"<<endl<<endl;; 84 printA(); 85 int pre=-1; 86 int prevalue=0; 87 for(int i=1;i<=n;i++){ 88 //判断离散化的时候两个值是否相同 89 //离散化很简单,就是排序后一个个输出就好 90 //下标的话依次递增就好了 91 if(pre!=a[i].v){ 92 pre=a[i].v; 93 a[i].v=++prevalue; 94 } 95 else a[i].v=prevalue; 96 } 97 cout<<endl<<"-----------------离散化后-----------------"<<endl<<endl; 98 printA(); 99 //这部分就是排序后给它逆回来 100 for(int i=1;i<=n;i++){ 101 cout<<"i: "<<i<<" a[i].id: "<<a[i].id<<" a[i].v:"<<a[i].v<<endl; 102 b[a[i].id]=a[i].v; 103 } 104 printB(); 105 long long s=0; 106 //逆序求解 107 cout<<endl<<"-----------------逆序求解-----------------"<<endl<<endl; 108 printC(); 109 for(int i=n;i>=1;i--){ 110 cout<<"i: "<<i<<endl; 111 Change(b[i]); 112 s+=Query(b[i]-1); 113 printC(); 114 cout<<"i: "<<i<<" b[i]: "<<b[i]<<" Query(b[i]-1):"<<Query(b[i]-1)<<endl; 115 } 116 cout<<endl<<"-----------------结果-----------------"<<endl<<endl;; 117 cout<<s<<endl;; 118 return 0; 119 }
运行过程:
a数组
id: 1 2 3 4 5
value: 2 3 1 5 4
-----------------排序后-----------------
a数组
id: 3 1 2 5 4
value: 1 2 3 4 5
-----------------离散化后-----------------
a数组
id: 3 1 2 5 4
value: 1 2 3 4 5
i: 1 a[i].id: 3 a[i].v:1
i: 2 a[i].id: 1 a[i].v:2
i: 3 a[i].id: 2 a[i].v:3
i: 4 a[i].id: 5 a[i].v:4
i: 5 a[i].id: 4 a[i].v:5
b数组
b[i]: 2 3 1 5 4
-----------------逆序求解-----------------
c数组
c[i]: 0 0 0 0 0
i: 5
c数组
c[i]: 0 0 0 1 0
i: 5 b[i]: 4 Query(b[i]-1):0
i: 4
c数组
c[i]: 0 0 0 1 1
i: 4 b[i]: 5 Query(b[i]-1):1
i: 3
c数组
c[i]: 1 1 0 2 1
i: 3 b[i]: 1 Query(b[i]-1):0
i: 2
c数组
c[i]: 1 1 1 3 1
i: 2 b[i]: 3 Query(b[i]-1):1
i: 1
c数组
c[i]: 1 2 1 4 1
i: 1 b[i]: 2 Query(b[i]-1):1
-----------------结果-----------------
3
这里的前缀和是比这个数小的个数,比如说倒数第二个数5,那么就是求的5后面比我小的数之和,也就是4的前缀和。
树状数组在这里用的就是前缀和。
测试离散化:
输入数据:
5
4 6 2 10 8
运行过程:
a数组
id: 1 2 3 4 5
value: 4 6 2 10 8
-----------------排序后-----------------
a数组
id: 3 1 2 5 4
value: 2 4 6 8 10
-----------------离散化后-----------------
a数组
id: 3 1 2 5 4
value: 1 2 3 4 5
i: 1 a[i].id: 3 a[i].v:1
i: 2 a[i].id: 1 a[i].v:2
i: 3 a[i].id: 2 a[i].v:3
i: 4 a[i].id: 5 a[i].v:4
i: 5 a[i].id: 4 a[i].v:5
b数组
b[i]: 2 3 1 5 4
-----------------逆序求解-----------------
c数组
c[i]: 0 0 0 0 0
i: 5
c数组
c[i]: 0 0 0 1 0
i: 5 b[i]: 4 Query(b[i]-1):0
i: 4
c数组
c[i]: 0 0 0 1 1
i: 4 b[i]: 5 Query(b[i]-1):1
i: 3
c数组
c[i]: 1 1 0 2 1
i: 3 b[i]: 1 Query(b[i]-1):0
i: 2
c数组
c[i]: 1 1 1 3 1
i: 2 b[i]: 3 Query(b[i]-1):1
i: 1
c数组
c[i]: 1 2 1 4 1
i: 1 b[i]: 2 Query(b[i]-1):1
-----------------结果-----------------
3