Inversion
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 5250 Accepted Submission(s): 1845
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
Author
Xiaoxu Guo (ftiasch)
Source
题意:
给你一个排序,你可以交换k次相邻的数,输出最好方案的最少的逆序数对。
POINT:
容易可知,每次交换都可以减少一个逆序数对。
所以只要求出原始的逆序数对,减去k,再与0比较一下就好了。
求逆序数对
1:因为数比较大,但是个数才1e5,用离散化后树状数组。
2:归并排序。
【训练赛的时候,写树状数组写错TLE,写线段树数组开小了,错了8发,真要反省一下。那么简单的题】
归并:
#include <string>
#include <string.h>
#include <iostream>
#include <queue>
#include <math.h>
#include <stdio.h>
using namespace std;
#define LL long long
const LL maxn = 1e5+55;
LL a[maxn];
LL ans=0;
void merge(LL l,LL mid,LL r)
{
LL now=0;
LL ll=l;
LL rr=mid+1;
LL cnt[maxn];
while(ll<=mid&&rr<=r){
if(a[ll]<=a[rr]){
cnt[++now]=a[ll++];
}else{
cnt[++now]=a[rr++];
ans+=mid-ll+1;
}
}
while(ll<=mid){
cnt[++now]=a[ll++];
}
while(rr<=r){
cnt[++now]=a[rr++];
}
for(LL i=1;i<=now;i++){
a[l+i-1]=cnt[i];
}
}
void bf(LL l,LL r)
{
if(l==r) return;
LL mid=(l+r)>>1;
bf(l,mid);
bf(mid+1,r);
merge(l,mid,r);
}
int main()
{
LL n,k;
while(~scanf("%lld %lld",&n,&k)){
ans=0;
for(LL i=1;i<=n;i++) scanf("%lld",&a[i]);
bf(1,n);
printf("%lld\n",max(ans-k,1LL*0));
}
return 0;
}
树状数组:
#include<iostream>
#include<iomanip>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <stack>
#include <cmath>
using namespace std;
typedef long long LL;
const LL maxn = 2*1e5+33;
LL a[maxn];
LL now[maxn];
LL sum[maxn];
LL n,k;
LL cnt=0;
LL lowbit(LL x)
{
return x&-x;
}
void add(LL x,LL p)
{
for(LL i=x;i<=cnt;i+=lowbit(i)){
sum[i]++;
}
}
LL query(LL x)
{
LL ans=0;
for(LL i=x;i>=1;i-=lowbit(i)){
ans+=sum[i];
}
return ans;
}
int main()
{
while(~scanf("%lld %lld",&n,&k)){
cnt=0;
for(LL i=1;i<=n;i++){
sum[i]=0;
scanf("%lld",&a[i]);
now[i]=a[i];
}
sort(now+1,now+1+n);
now[0]=-111;
for(LL i=1;i<=n;i++){
if(now[i]==now[i-1]) continue;
now[++cnt]=now[i];
}
LL ans=0;
for(LL i=1;i<=n;i++){
a[i]=(LL)(lower_bound(now+1,now+1+cnt,a[i])-now);
add(a[i],1);
ans+=query(cnt)-query(a[i]);
}
ans=max(1LL*0,ans-k);
printf("%lld\n",ans);
}
return 0;
}