模板——權值線段樹(逆序對)
阿新 • • 發佈:2017-08-09
code logs d+ produce inpu body click end sequence Ultra-QuickSort
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
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
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.
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
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
Source
Waterloo local 2005.02.05 大意就是給若幹個長度為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 }神奇的代碼
模板——權值線段樹(逆序對)