链接:https://www.nowcoder.com/acm/contest/77/A
来源:牛客网
逆序数
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。比如一个序列为4 5 1 3 2, 那么这个序列的逆序数为7,逆序对分别为(4, 1), (4, 3), (4, 2), (5, 1), (5, 3), (5, 2),(3, 2)。
输入描述:
第一行有一个整数n(1 <= n <= 100000), 然后第二行跟着n个整数,对于第i个数a[i],(0 <= a[i] <= 100000)。
输出描述:
输出这个序列中的逆序数
示例1
输入
5 4 5 1 3 2
输出
7
先离散化,得到数组b[i],
a:88 11 62 5 23 b:5 2 4 1 3
i为1,那么在5的位置+1,
即 1 2 3 4 5
sum[i] 0 0 0 0 1
在计算5及5之前有几个数,为1个数,再用总数-1=4,代表和5组成逆序对的有4个数。
1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 7 int T, n; 8 int sum[100005]; 9 10 struct node 11 { 12 int pos, x; 13 }a[100005]; 14 int b[100005]; 15 16 bool cmp(node x, node y) 17 { 18 return x.x < y.x; 19 } 20 21 void update(int pos, int val) 22 { 23 while (pos <= n) 24 { 25 sum[pos] += val; 26 pos += (pos&(-pos));//加上最末尾的1所代表的个数,12,1100,+4+8 27 } 28 } 29 30 int query(int pos) 31 { 32 int rec = 0;//13为1101,减去末尾的1(1),1100,再减去末尾的1(4),1000,再减(8),000 33 while (pos > 0) 34 { 35 rec+=sum[pos]; 36 pos -= (pos&(-pos)); 37 } 38 return rec; 39 } 40 41 int main() 42 { 43 long long nxs = 0; 44 cin >> n; 45 memset(sum, 0, sizeof(sum)); 46 for (int i = 1,x; i <= n; i++) 47 { 48 cin >> a[i].x; 49 a[i].pos = i;//记录原先的位置,88 11 62 5 23 50 } 51 sort(a + 1, a + n + 1, cmp); 52 for (int i = 1; i <= n; i++) 53 { 54 b[a[i].pos] = i;//5原来在4的位置b【4】=1 55 //a:88 11 62 5 23 56 //b:5 2 4 1 3 57 } 58 /*for (int i = 1; i <= n; i++) 59 { 60 cout << b[i] << " "; 61 } 62 cout << endl;*/ 63 for (int i = 1; i <= n; i++) 64 { 65 update(b[i], 1); 66 int temp = query(b[i]); 67 nxs += b[i] - temp; 68 } 69 cout << nxs << endl; 70 }