欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HDU4911-Inversion

程序员文章站 2021-12-30 07:15:27
...

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.
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).
Output
For each tests:

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次冒泡交换后还剩多少个逆序对?

解析:
这道题有两种解法:
(1)树状数组:这就是裸题了
(2)分治法

树状数组:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100005

using namespace std;

struct node{
	int v,id;
};

node book[N];
long long tree[N];
int val[N];
int Max;

bool cmp(node a,node b)
{
	return a.v<b.v;
}

int lowbit(int x)
{
	return x&-x;
}

void updata(int x)
{
	while(x<=Max)
	{
		tree[x]++;
		x+=lowbit(x);
	}
}

long long Sum(int x)
{
	long long sum=0;
	while(x>0)
	{
		sum+=tree[x];
		x-=lowbit(x);
	}
	return sum;
}

long long query(int x)
{
	return Sum(Max)-Sum(x);
}

int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		long long sum=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&book[i].v);
			book[i].id=i;
		}
		sort(book+1,book+n+1,cmp);
		int t=val[book[1].id]=1;
		for(int i=2;i<=n;i++)
		{
			if(book[i].v!=book[i-1].v)
				t++;
			val[book[i].id]=t;
		}
		Max=t;
		for(int i=1;i<=n;i++)
		{
			sum+=query(val[i]);
			updata(val[i]);
		}
		if(sum<=m)
			printf("0\n");
		else
			printf("%lld\n",sum-m);
		memset(tree,0,sizeof(tree));
	}
	return 0;
 } 

分治法:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100005
 
using namespace std;
 
int book[N],help[N];
long long sum;
 
void solve(int *book,int l,int m,int r)
{
    int l1=l,l2=m+1,c=l;
    while(l1<=m && l2<=r)
    {
        if(book[l1]<=book[l2])
            help[c++]=book[l1++];
        else
        {
            help[c++]=book[l2++];
            sum+=m-l1+1;
        }
    }
    while(l1<=m)
        help[c++]=book[l1++];
    while(l2<=r)
        help[c++]=book[l2++];
    for(int i=l;i<=r;i++)
        book[i]=help[i];
}
 
void merge_sort(int *book,int l,int r)
{
    if(l>=r) 
		return;
    int mid=(l+r)>>1;
    merge_sort(book,l,mid);
    merge_sort(book,mid+1,r);
    solve(book,l,mid,r);
}
 
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&book[i]);
        sum=0;
        merge_sort(book,1,n);
        sum = max(sum-k,0LL);
        printf("%I64d\n",sum);
    }
    return 0;
}

推荐阅读