给你一串数字,然后给你最多进行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 "); else printf("%I64d " ,sum - m); } return 0; }