小记:看到这题感到莫名的熟悉感,大概是因为蓝桥杯最后一题也是求这样的逆序对吧,而我写的解题报告也是用树状数组实现的。所以直接动手
思路:题意就是求一个序列中的逆序对数,hdu2689和这个题类似(点击看那题的解题报告),只不过这题的数比较大,不能直接对元素数用树状树状,为此我们必须离散化,
离散化是,用一个结构体数组,其保存元素值和次序id:
struct node {
int num,id;
} a[MAX_];
然后对该数组以元素值从小到大排序,
bool cmp2(const node &a,const node& b) {
return a.num < b.num;
}
如果某两个数的值是相等的,那么我们就令其为同一个id,
if(a[i].num!=a[i-1].num) b[a[i].id]=i;
else b[a[i].id]=b[a[i-1].id];
保证了元素值与id是互相唯一对应的了,那么就可以对id用树状数组求解了。
对每个元素的id求出其前面大于它id的数的个数,算出总和就是answer了:
for(int i=1; i<=n; i++) {
add(b[i],1);
ans+=sum(n)-sum(b[i]);
}
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define eps 10e-8
const int MAX_ = 500010;
const int INF = 0x7fffffff;
const int MAX = 500010;
struct node {
int num,id;
} a[MAX_];
int C[MAX_], b[MAX_];
int T, n, m,l ,r;
int lowbit(int x) {
return x&(-x);
}
void add(int x,int num) {
while(x < MAX) {
C[x] += num;
x += lowbit(x);
}
}
int sum(int x) {
int cnt = 0;
while(x > 0) {
cnt += C[x];
x -= lowbit(x);
}
return cnt;
}
bool cmp2(const node &a,const node& b) {
return a.num < b.num;
}
int main() {
while(scanf("%d",&n),n) {
for(int i=1; i<=n; i++) {
scanf("%d",&a[i].num);
a[i].id = i;
}
mst(b,0);
mst(C,0);
//离散化
sort(a+1,a+n+1,cmp2);
b[a[1].id]=1;
for(int i=2; i<=n; i++) {
if(a[i].num!=a[i-1].num) b[a[i].id]=i;
else b[a[i].id]=b[a[i-1].id];
}
long long ans=0;
for(int i=1; i<=n; i++) {
add(b[i],1);
ans+=sum(n)-sum(b[i]);
}
printf("%I64d\n",ans);
}
return 0;
}