模板——权值线段树(逆序对)
Posted ~Lanly~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板——权值线段树(逆序对)相关的知识,希望对你有一定的参考价值。
Ultra-QuickSort
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 62455 | Accepted: 23259 |
Description
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
Ultra-QuickSort produces the output
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
Source
大意就是给若干个长度为n的序列求逆序对个数。
权值线段树维护的是某个值出现的次数,所以一开始是空树(换句话说就不用建树了2333),然后不断按顺序从左到右插入点,很显然每插入一个点就记录比这个点大的个数即为此时的逆序对个数,然后累计即可。
因为数值可达9亿9千9百9十9万9千9百9十9,但个数最多只有500000,所以先离散后插入。(ans要long long!!!)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 int n,a[500005],tmp[500005],size; 7 long long ans,cnt[2000005]; 8 void init(int root,int l,int r,int x){ 9 if ((l==r)&&(l==x)) { 10 cnt[root]++; 11 return; 12 } 13 int mid=(l+r)>>1; 14 if (x<=mid) init(root<<1,l,mid,x); 15 else if (x>mid) init(root<<1|1,mid+1,r,x); 16 cnt[root]=cnt[root<<1]+cnt[root<<1|1]; 17 } 18 long long sum(int root,int l,int r,int x,int y){ 19 if ((x<=l)&&(y>=r)) return cnt[root]; 20 long long anss=0; 21 int mid=(l+r)>>1; 22 if (x<=mid) anss+=sum(root<<1,l,mid,x,y); 23 if (y>mid) anss+=sum(root<<1|1,mid+1,r,x,y); 24 return anss; 25 } 26 int main(){ 27 scanf("%d",&n); 28 while (n){ 29 memset(a,0,sizeof(a)); 30 memset(cnt,0,sizeof(cnt)); 31 memset(tmp,0,sizeof(tmp)); 32 size=0; 33 ans=0; 34 for (int i=1;i<=n;i++){ 35 scanf("%d",&a[i]); 36 tmp[i]=a[i]; 37 } 38 sort(tmp+1,tmp+1+n); 39 size=unique(tmp+1,tmp+1+n)-(tmp+1); 40 for (int i=1;i<=n;i++) 41 a[i]=lower_bound(tmp+1,tmp+1+size,a[i])-(tmp+1)+1; 42 for (int i=1;i<=n;i++){ 43 init(1,1,n,a[i]); 44 ans+=sum(1,1,n,a[i]+1,n); 45 } 46 printf("%lld\n",ans); 47 scanf("%d",&n); 48 } 49 return 0; 50 }
以上是关于模板——权值线段树(逆序对)的主要内容,如果未能解决你的问题,请参考以下文章