逆序对

Posted 范仁义

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆序对相关的知识,希望对你有一定的参考价值。

逆序对

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
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

以上是关于逆序对的主要内容,如果未能解决你的问题,请参考以下文章

c++ 逆序对

第三次过程性考核

逆序对的求解逆序对个数问题

递归逆序的使用

逆序对

树状数组求逆序对