题干:
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order.
For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
题目大意:
大概题意就是给你n个数,让你求逆序对的个数。
解题报告:
这题是求逆序对的个数,直接上权值树状数组,然后求个逆序数就可以了,这里提供两种思路,一种是枚举每一个数然后看截止当前,他前面出现过多少比他大的(查后缀1的个数)。另一种是看截止当前,他后面有多少比他小的,也就是还有多少比他小的还没出现(查前缀0的个数)。
在此附上对应两种方法的AC代码:
AC代码1:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX = 500005 ;
int a[500005],b[MAX],c[500005];
int n;
int lowbit(int x){return x&-x;}
void update(int x,int val) {while(x<MAX) {c[x] += val;x+=lowbit(x);}
}
int query(int x) {int res = 0;while(x>0) {res += c[x];x-=lowbit(x);}return res;
}
int main()
{while(~scanf("%d",&n)) {if(n==0) break;ll ans = 0;memset(c,0,sizeof c);for(int i = 1; i<=n; i++) scanf("%d",a+i),b[i] = a[i];sort(b+1,b+n+1);int top = unique(b+1,b+n+1) - b - 1;for(int i = 1; i<=n; i++) {int pos = lower_bound(b+1,b+top+1,a[i]) - b;update(pos,1);ans += query(MAX-1) - query(pos);//ans += (pos-1)-query(pos-1);
// printf("yy\n");}printf("%lld\n",ans);}return 0 ;}
总结:
1.注意update和query中while都不能写等号。查询query的时候越界问题,所以需要查询MAX-1;
AC代码2:
//没写n==0的break?
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX = 500005 ;
int a[500005],b[MAX],c[500005];
int n;
int lowbit(int x){return x&-x;}
void update(int x,int val) {while(x<=MAX) {c[x] += val;x+=lowbit(x);}
}
int query(int x) {int res = 0;while(x>0) {res += c[x];x-=lowbit(x);}return res;
}
int main()
{while(~scanf("%d",&n)) {if(n==0) break;ll ans = 0;memset(c,0,sizeof c);for(int i = 1; i<=n; i++) scanf("%d",a+i),b[i] = a[i];sort(b+1,b+n+1);int top = unique(b+1,b+n+1) - b - 1;for(int i = 1; i<=n; i++) {int pos = lower_bound(b+1,b+top+1,a[i]) - b;update(pos,1);ans += (pos-1)-query(pos-1);}printf("%lld\n",ans);}return 0 ;}