小记:看到这题感到莫名的熟悉感,大概是因为蓝桥杯最后一题也是求这样的逆序对吧,而我写的解题报告也是用树状数组实现的。所以直接动手
思路:题意就是求一个序列中的逆序对数,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; }