title link : http://acm.hdu.edu.cn/showproblem.php?pid=4911
The main problem : Can exchange a maximum of k times, the minimum number of reverse logarithm
Problem Solving Ideas :
The inverse number theorem, when the inverse logarithm is greater than 0 o'clock, if ak<ak+1, then the inverse of the exchange after the logarithm +1, the reverse-1.
Set primitive sequence minimum inverse logarithm =cnt
So, the minimum inverse logarithm max (0,cnt-k) to Exchange K times
Naïve violence complexity O (n^2) is not available in order to find the minimum inverse logarithm of primitive sequence
There are two methods of O (NLOGN):
① Sort inside Calculation:
The main use of the merge sort within the characteristics, that is, the adjacent two merge sequence reverse case does not change, [5,4,2,1] to [4,5], [up]
The reverse order of 4 and 1,5 and 2 did not change after sorting corrected. Using this property, the inverse logarithm is counted when sorting two sub-sequence merges in the merge sort.
That is, edge sorting, edge statistics, assuming that the left and right sequences are recursively passed through the sequence starting with 0 renumber, the initial offset, i=j=0
When Left[i]>right[j] appears in reverse order, cnt+= (Leftnum-i), which is the current right[j] element and Left[i], and later elements all form reverse pairs.
After merging, recursion continues to merge larger sequences. Statistical complexity = sorting complexity O (NLOGN)
Note the spelling of the merge sort, the left and right tails to be set to INF, so that after running the sequence will be directly compared with the INF.
G#include"Cstdio"#include"algorithm"#defineLL Long Longusing namespacestd;inta[100005]; LL CNT=0;voidMergeintLintMintR) { intlnum=m-l+1, rnum=r-m; int*left=New int[lnum+1],*right=New int[rnum+1]; for(intI=0; i<lnum;i++) left[i]=a[l+i]; for(intI=0; i<rnum;i++) right[i]=a[m+1+i]; Left[lnum]=right[rnum]=0x3fffffff; intI=0, j=0; for(intk=l;k<=r;k++) { if(left[i]<=Right[j]) {A[k]=Left[i]; I++; } Else{A[k]=Right[j]; J++; CNT+ = (lnum-i); } }}voidMergeSort (intLintR) { if(l<r) {intM= (r-l)/2+l; MergeSort (L,M); MergeSort (M+1, R); Merge (L,m,r); }}intMain () {//freopen ("In.txt", "R", stdin); intn,k; while(SCANF ("%d%d", &n,&k)! =EOF) {CNT=0; for(intI=0; i<n;i++) scanf ("%d",&A[i]); MergeSort (0, N-1); printf ("%i64d\n", Max (LL)0, cnt-k)); }}
View Code
② tree-like array:
It's a wonderful way. You first use the sort that records the original location POS, and then discretization the sorted elements.
such as sequence 5,1,1, discretized into 2,1,1, the tree array Sum[i] records the number of times the discretization position is activated, that is, add (hash[i],1)
such as discretization position, the initial value [0,0], first in accordance with the input order of the add discretization position.
Enter the 5,sum case [0,1], then the tree-like array getsum the number of activations in the order array to this number.
With the original position i-getsum, the result is, does not contain this number, before the number of activations, that is, the statistical reverse case.
So when is 1, here because of 1-1=0, that is, before 5 in reverse order.
Enter 1,sum condition [1,1],getsum=1,i-getsum=1, there is an inverse pair. [5,1], the reason is 5 was activated before 1.
Enter 1,sum condition [2,1],getsum=2, I-getsum=1, there is an inverse pair. Here to do add to the number of repetitions, because the number of repetitions, I increased,
Getsum also to the corresponding increase, otherwise, will and the previous repetition count of the weight, such as 3-1=2,, is counted heavy.
#include"Cstdio"#include"algorithm"#include"CString"#include"Map"using namespacestd;#defineLL Long Longintsum[100005],n,k,val,n; LL CNT;intLowbit (intx) {returnx& (-x);}structnum{intVal,pos; Num () {} num (intValintPOS): Val (val), POS (POS) {}BOOL operator< (ConstNum &a)Const{returnval<A.val;}} a[100005]; LL Getsum (intx) {LL ret=0; while(x>0) {ret+=Sum[x]; X-=lowbit (x); } returnret;}voidUpdateintXintd) { while(x<=N) {sum[x]+=D; X+=lowbit (x); }}intMain () {Freopen ("In.txt","R", stdin); while(SCANF ("%d%d", &n,&k)! =EOF) {memset (sum,0,sizeof(sum)); Map<LL,LL>Hash; CNT=0; for(intI=0; i<n;i++) {scanf ("%d",&val); A[i]=Num (val,i); } sort (A,a+N); intId=1; hash[a[0].pos]=ID; for(intI=1; i<n;i++)//discretization of { if(a[i].val==a[i-1].val) hash[a[i].pos]=ID; Elsehash[a[i].pos]=++ID; } N=ID; for(intI=0; i<n;i++) {update (hash[i],1); CNT+ = (i+1-getsum (Hash[i])); } printf ("%i64d\n", Max (LL)0, cnt-k)); }}
View Code
HDU 4911 (tree array + reverse order number)