POJ_2299_Ultra-QuickSort
牢骚:~做了那么久树状数组卡死在离散化,无语到透顶。
离散化的定义:把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
这题是赤裸裸的求逆序对,为何要用离散化?
首先,这恶心的题目给出a[i]的范围居然是10亿,这还求啥逆序对,开个辅助数组c,直接MLE了,还好出题人人性化了点,给了个数组长度n,1<=n<50,000,还有希望...
然后,我们根据a[i]的值从小到大排列,留着它的id...然后遍历
#include <cstdio> #include <cmath> #include<vector> #include <algorithm> using namespace std; #define N 500005 #define LL long long int n,c[N]; struct point { int val,id; }p[N]; int sum(int x) { int ret=0; while(x) { ret+=c[x]; x-=x&-x; } return ret; } void add(int x) { while(x<=n) { c[x]++; x+=x&-x; } } bool cmp(point a,point b) { if(a.val != b.val) //注意有相等的元素 ,必须这样写 return a.val<b.val; return a.id <b.id; } int main() { int i,j,k; while(~scanf("%d",&n),n) { for(i=1;i<=n;++i) { scanf("%d",&p[i].val); p[i].id=i; c[i]=0; } sort(p+1,p+1+n,cmp); LL ans=0; //一般n在10W以上,求逆序对的题目就可以直接用long long了 for(i=1;i<=n;++i) { /* 为啥可以这样离散化? 想想啊,假设i<j,p[i].id<p[j].id,然后由排序,我们知道p[i].num一定会小于等于p[j].num, 于是p[i]、p[j]就顺利的成为了一对非严格递增的顺序对 */ add(p[i].id); ans+=i-sum(p[i].id); } printf("%I64d\n",ans); } return 0; }