Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 46504 | Accepted: 16945 |
Description
Input
Output
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
求逆序数思路:首先初始化所有节点对应区间为0,然后优先插入最大值,并把最大值所在位置赋值为1,再查询插入位置前有多少个数(就是求1到 当前插入位置-1 之和),每次累加即是所有逆序对。
线段树(不用lazy思想)766ms:
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 500000+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) { return a.val > b.val; } 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 n, i; LL ans; while(scanf("%d", &n), 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 938ms:
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 500000+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) { return a.val > b.val; } 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 n, i; LL ans; while(scanf("%d", &n), 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; }
树状数组 500ms:
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 500000 #define LL long long using namespace std; int c[MAX]; int n; struct record { int val, pos;//记录数值 和 位置 }num[MAX]; bool cmp(record a,record b) { return a.val > b.val; } int lowbit(int x) { return x&(-x); } int sum(int x) { int s = 0; while(x > 0) { s += c[x]; x -= lowbit(x); } return s; } void update(int x) { while(x <= n) { c[x] += 1; x += lowbit(x); } } int main() { int i, j; LL ans; while(scanf("%d", &n), 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); ans += sum(num[i].pos-1);//统计前面有多少个数 } printf("%lld\n", ans); } return 0; }
归并排序:391ms
#include <cstdio> #include <cstring> #define MAX 500000+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 n; int i, j; while(scanf("%d", &n),n) { for(i = 0; i < n; i++) { scanf("%d", &a[i]); } ans = 0; Merge_sort(0,n-1); printf("%lld\n", ans); } return 0; }