您的位置:首页 > 其它

HDU 4911 Inversion(树状数组求逆序对数 + 数据离散化)

2017-08-17 15:05 387 查看
[align=left]Problem Description[/align]

bobo has a sequence a1,a2,…,an. He is allowed to swap twoadjacent 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 ai>aj.
 

[align=left]Input[/align]

The input consists of several tests. For each tests:

The first line contains 2 integers n,k (1≤n≤105,0≤k≤109). The second line contains n integers a1,a2,…,an (0≤ai≤109).
 

[align=left]Output[/align]

For each tests:

A single integer denotes the minimum number of inversions.
 

[align=left]Sample Input[/align]

3 1
2 2 1
3 0
2 2 1

 

[align=left]Sample Output[/align]

1
2

 
题目大意:给定 n 个数,和最多 k 次的调整,每次只能选择交换相邻的两个数,问最少能得到的逆序对的个数。
观察一下不难发现交换任意一对最多减少一个逆序对,不影响其他部分,那么思路及很简单了。求出逆序对的个数,减 k 即可,需要注意的是,k 大于原串逆序对个数时直接输出零就行。
求逆序对我是用树状数组写的,所以对数据离散化了一下,也可以用分治的思想直接求。
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1e5 + 5;
ll t[maxn],sub[maxn],a[maxn];
bool vis[maxn];
int n;
int lowbit(int x)
{
return x & -x;
}
ll query(int x)
{
ll sum = 0;
while(x > 0)
{
sum += t[x];
x -= lowbit(x);
}
return sum;
}
void add(int x,int v)
{
while(x <= n)
{
t[x] += v;
x += lowbit(x);
}
}
int main()
{
int k;
ll sum;
while(scanf("%d %d",&n,&k) != EOF)
{
sum = 0;
memset(t,0,sizeof(t));
memset(vis,false,sizeof(vis));
for(int i = 0;i < n; ++i) scanf("%d",&a[i]),sub[i] = a[i];
sort(sub,sub + n);
int len = unique(sub,sub + n) - sub;
for(int i = 0;i < n; ++i)
{
a[i] = lower_bound(sub,sub + len,a[i]) - sub + 1;
}
for(int i = 0;i < n; ++i)
{
sum += (query(n) - query(a[i]));
add(a[i],1);
}
printf("%lld\n",k > sum ? 0 : sum - k);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: