0
点赞
收藏
分享

微信扫一扫

hdu4911 简单树状数组

笙烛 2022-07-18 阅读 76

题意:
     给你一串数字,然后给你最多进行k次交换(只能交换相邻的)问交换后的最小逆序数是多少。


思路:

     首先要知道的一个就是给你一个序列,每次只能交换相邻的位置,把他交换成一个递增序列所需要的最少步数等于整个序列的逆序数,在转化到这个题目,我们只要求出个逆序数,然后输出逆序数 - k就行了,如果是负数输出0。



#include<stdio.h>
#include<string.h>
#include<algorithm>

#define N 100000 + 10

using namespace std;

typedef struct
{
int num ,id;
}NODE;

NODE node[N];

__int64 num[N];
int hash[N];
int lowbit(int x)
{
return x & -x;
}

void update(int x ,__int64 a ,int n)
{
for(int i = x ;i <= n ;i += lowbit(i))
num[i] += a;
}

__int64 find(int x)
{
__int64 sum = 0;
for(int i = x ;i > 0 ;i -= lowbit(i))
sum += num[i];
return sum;
}

bool camp(NODE a ,NODE b)
{
return a.num < b.num;
}

int main ()
{
int n ,i ,a;
__int64 m ,sum;
while(~scanf("%d %I64d" ,&n ,&m))
{
for(i = 1 ;i <= n ;i ++)
{
scanf("%d" ,&node[i].num);
node[i].id = i;
}
sort(node + 1 ,node + n + 1 ,camp);
int t = 0;
node[0].num = -1;
for(i = 1 ;i <= n; i ++)
{
if(node[i].num != node[i-1].num)
t ++;
hash[node[i].id] = t;
}
memset(num ,0 ,sizeof(num));
for(sum = 0 ,i = 1 ;i <= n ;i ++)
{
sum += (i - 1) - find(hash[i]);
update(hash[i] ,1 ,t);
}
if(sum < m) printf("0\n");
else printf("%I64d\n" ,sum - m);
}
return 0;
}




举报

相关推荐

0 条评论