求逆序数
时间限制:
2000 ms | 内存限制:
65535 KB
难度:
5
-
描述
-
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。
比如 1 3 2 的逆序数就是1。
-
输入
-
第一行输入一个整数T表示测试数据的组数(1<=T<=5)
每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000)
随后的一行共有N个整数Ai(0<=Ai<1000000000),表示数列中的所有元素。
数据保证在多组测试数据中,多于10万个数的测试数据最多只有一组。
输出
- 输出该数列的逆序数 样例输入
-
2 2 1 1 3 1 3 2
样例输出
-
0 1
-
线段树lazy:1536ms
-
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 1000000+10 #define LL long long using namespace std; int sum[MAX<<2]; struct record { int val, pos; }num[MAX]; bool cmp(record a,record b) { if(a.val != b.val) return a.val > b.val; else return a.pos > b.pos; } void PushUp(int o) { sum[o] = sum[o<<1] + sum[o<<1|1]; } void build(int o, int l, int r)//建树 { sum[o] = 0; if(l == r) return ; int mid = (l+r) >> 1; build(o<<1, l, mid); build(o<<1|1, mid+1, r); PushUp(o); } int query(int o, int l, int r, int L, int R)//查询 { if(L <= l && R >= r) { return sum[o]; } int mid = (l+r) >> 1; int res = 0; if(L <= mid) res += query(o<<1, l, mid, L, R); if(R > mid) res += query(o<<1|1, mid+1, r, L, R); return res; } void update(int o, int l, int r, int L)//更新 { if(l == r) { sum[o] += 1; return ; } int mid = (l+r) >> 1; if(L <= mid) update(o<<1, l, mid, L); else update(o<<1|1, mid+1, r, L); PushUp(o); } int main() { int t, n, i; LL ans; scanf("%d", &t); while(t--) { scanf("%d", &n); build(1, 1 ,n); for(i = 0; i < n; i++) { scanf("%d", &num[i].val); num[i].pos = i + 1; } sort(num, num+n, cmp); ans = 0; for(i = 0; i < n; i++) { update(1, 1, n, num[i].pos); if(num[i].pos == 1) continue; ans += query(1, 1, n, 1, num[i].pos-1); } printf("%lld\n", ans); } return 0; }
-
线段树(不用lazy):1384ms
-
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 1000000+10 #define LL long long using namespace std; int sum[MAX<<2]; struct record { int val, pos; }num[MAX]; bool cmp(record a,record b) { if(a.val != b.val) return a.val > b.val; else return a.pos > b.pos; } void build(int o, int l, int r)//建树 { sum[o] = 0; if(l == r) return ; int mid = (l+r) >> 1; build(o<<1, l, mid); build(o<<1|1, mid+1, r); } int query(int o, int l, int r, int L, int R)//查询 { if(L == l && R == r) { return sum[o]; } int mid = (l+r) >> 1; if(R <= mid) return query(o<<1, l, mid, L, R); else if(L > mid) return query(o<<1|1, mid+1, r, L, R); else return query(o<<1, l, mid, L, mid) + query(o<<1|1, mid+1, r, mid+1, R); } void update(int o, int l, int r, int L)//更新 { sum[o] += 1; if(l == r) return ; int mid = (l+r) >> 1; if(L <= mid) update(o<<1, l, mid, L); else update(o<<1|1, mid+1, r, L); } int main() { int t, n, i; LL ans; scanf("%d", &t); while(t--) { scanf("%d", &n); build(1, 1 ,n); for(i = 0; i < n; i++) { scanf("%d", &num[i].val); num[i].pos = i + 1; } sort(num, num+n, cmp); ans = 0; for(i = 0; i < n; i++) { update(1, 1, n, num[i].pos); if(num[i].pos == 1) continue; ans += query(1, 1, n, 1, num[i].pos-1); } printf("%lld\n", ans); } return 0; }
-
树状数组:1156ms
-
#include <cstdio> #include <cstring> #include <algorithm> #define LL long long #define MAX 1000000+10 using namespace std; int n; int c[MAX<<2]; struct record { int val, pos; }num[MAX]; bool cmp(record a,record b) { if(a.val != b.val) return a.val > b.val; else return a.pos > b.pos; } int lowbit(int x) { return x&(-x); } void update(int x) { while(x <= n) { c[x] += 1; x += lowbit(x); } } LL sum(int x) { LL s = 0; while(x > 0) { s += c[x]; x -= lowbit(x); } return s; } int main() { int t; int i, j; LL ans; //int ans; scanf("%d", &t); while(t--) { scanf("%d", &n); memset(c, 0, sizeof(c)); for(i = 0; i < n; i++) { scanf("%d", &num[i].val); num[i].pos = i + 1; } sort(num, num+n, cmp); ans = 0; for(i = 0; i < n; i++) { update(num[i].pos); if(num[i].pos == 1) continue; ans += sum(num[i].pos - 1); } printf("%lld\n", ans); } return 0; }
-
归并排序:456ms
-
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 1000000+10 #define LL long long using namespace std; int a[MAX], tmp[MAX]; LL ans; void Merge(int l, int m, int r) { int i = l; int j = m + 1; int k = l; while(i <= m && j <= r) { if(a[i] > a[j]) { tmp[k++] = a[j++]; ans += m - i + 1; } else { tmp[k++] = a[i++]; } } while(i <= m) tmp[k++] = a[i++]; while(j <= r) tmp[k++] = a[j++]; for(int i = l; i <= r; i++) { a[i] = tmp[i]; } } void Merge_sort(int l,int r) { if(l < r) { int m = (l + r) >> 1; Merge_sort(l,m); Merge_sort(m+1,r); Merge(l,m,r); } } int main() { int t, n; int i, j; LL res; scanf("%d", &t); while(t--) { scanf("%d", &n); for(i = 0; i < n; i++) { scanf("%d", &a[i]); } ans = 0; Merge_sort(0,n-1); printf("%lld\n", ans); } return 0; }
-
第一行输入一个整数T表示测试数据的组数(1<=T<=5)