POJ 2299Ultra-QuickSort
题意:线段树求逆序对经典题目,需要离散处理,但是用stl处理的话会T,手动二分处理即可;
#include<algorithm> #include<iostream> #include<map> #include<set> #include<vector> #include<queue> #include<stack> #include<cstring> #include<cstdio> #define N 500005 using namespace std; typedef struct node{ int x;int y;int date; }node; bool cmp(int a,int b){ return a>b; } node a[4*N]; void built(int root,int first,int end){ if(first==end){ a[root].x=first;a[root].y=end;a[root].date=0; return ; } int mid=(first+end)/2; built(root*2,first,mid); built(root*2+1,mid+1,end); a[root].x=a[root*2].x;a[root].y=a[root*2+1].y;a[root].date=0; } void U(int root,int first,int end,int e){ if(first==end){ a[root].date++; return ; } int mid=(first+end)/2; if(e<=mid) U(root*2,first,mid,e); else U(root*2+1,mid+1,end,e); a[root].date=a[root*2].date+a[root*2+1].date; } long long sum=0; void Q(int root,int first,int end,int l,int r){ if(l<=first&&end<=r){ sum+=a[root].date; return ; } int mid=(first+end)/2; if(l<=mid) Q(root*2,first,mid,l,r); if(r>mid) Q(root*2+1,mid+1,end,l,r); } long long b[N]; long long c[N]; long long e[N]; long long p[N]; int main(){ int m; while(scanf("%d",&m)==1&&m!=0){ for(int i=1;i<=m;i++){ scanf("%d",&b[i]); p[i]=b[i]; } sort(b+1,b+m+1,cmp); e[1]=b[1]; int k=1; for(int i=2;i<=m;i++){ if(b[i]!=b[i-1]){ k++; e[k]=b[i]; } } for(int i=1;i<=m;i++){ int first=1;int end=k; while(first<=end){ int mid=(first+end)/2; if(p[i]==e[mid]){ c[i]=mid; break; } else if(p[i]<e[mid]){ first=mid+1; } else{ end=mid-1; } } } built(1,1,k); long long ans=0; for(int i=1;i<=m;i++){ sum=0; if(c[i]==1){ U(1,1,k,c[i]); } else{ Q(1,1,k,1,c[i]-1); ans+=sum; U(1,1,k,c[i]);} } printf("%lld\n",ans); } return 0; }