Inversion
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1785 Accepted Submission(s): 711
Problem Description
bobo has a sequence a
1,a
2,…,a
n. He is allowed to swap two
adjacent numbers for no more than k times.
Find the minimum number of inversions after his swaps.
Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and a i>a j.
Find the minimum number of inversions after his swaps.
Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and a i>a j.
Input
The input consists of several tests. For each tests:
The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
Output
For each tests:
A single integer denotes the minimum number of inversions.
A single integer denotes the minimum number of inversions.
Sample Input
3 1 2 2 1 3 0 2 2 1
Sample Output
1 2读懂没明白怎么求, 题目大意:已知一个序列,操作k次之后求最小逆序数。 思路:求出来逆序对数sum,一共需要移动sum次,如果逆序对数不大于k,那么最少的的就是0,如果大于k,则用逆序对总数sum减去k,也就是说再移动sum-k次就到0 了。加油!!! 因为树状数组离散化需要排序,归并排序略快。分别为109ms和156ms下面分别是树状数组和归并排序解法:#include<cstdio>//归并排序解法 #include<cstring> #include<algorithm> using namespace std; #define MAX 100000+10 __int64 k,ans; int a[MAX],t1[MAX],t2[MAX]; void merge_sort(int start,int end,int mid){ int i,j,k; for(k=0,i=start;i<=mid;i++) t1[k++]=a[i]; t1[k]=INT_MAX; for(k=0,i=mid+1;i<=end;i++) t2[k++]=a[i]; t2[k]=INT_MAX; i=j=0; for(k=start;k<=end;k++){ if(t1[i]<=t2[j]){ a[k]=t1[i++]; }else{ ans+=(mid-start+1-i);//前半边的长度-比后边的x小的数=前半边比x大的数 a[k]=t2[j++]; } } } void merge(int start,int end){ if(end>start){ int mid=(start+end)>>1; merge(start,mid); merge(mid+1,end); merge_sort(start,end,mid); } } int main(){ int n; while(scanf("%d%I64d",&n,&k)!=EOF){ for(int i=0;i<n;i++) scanf("%d",&a[i]); ans=0; merge(0,n-1); ans-=k; if(ans<0) printf("0\n"); else printf("%I64d\n",ans); } return 0; }
#include<cstdio>//树状数组解法 #include<cstring> #include<algorithm> using namespace std; #define MAX 100000+10 struct Node{ int val,pos; }s[MAX]; __int64 ans,k; int n; int hash[MAX],C[MAX]; bool cmp(Node a,Node b){ if(a.val<b.val) return true; if(a.val==b.val&&a.pos<b.pos) return true; return false; } int lowbit(int x){ return x&(-x); } void Modify(int pos,int v){ while(pos<=n){ C[pos]+=v; pos+=lowbit(pos); } } int nSum(int pos){ int sum=0; while(pos>0){ sum+=C[pos]; pos-=lowbit(pos); } return sum; } int main(){ while(scanf("%d%I64d",&n,&k)!=EOF){ int i,j; for(i=1;i<=n;i++){ scanf("%d",&s[i].val); s[i].pos=i; } ans=0; memset(C,0,sizeof(C)); sort(s+1,s+n+1,cmp); for(i=1;i<=n;i++)hash[s[i].pos]=i;//按值排序后将值离散化 for(i=1;i<=n;i++){//按原来的位置开始访问 Modify(hash[i],1); ans+=(i-nSum(hash[i]));//前边的一共有i个,减去比hash[i]小的值和与等于的剩下就是比它大的个数 } if(ans-k>0)ans-=k; else ans=0; printf("%I64d\n",ans); } return 0; }