hdu4911 简单树状数组

题意:
     给你一串数字,然后给你最多进行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;
}
      
      

原文地址:https://www.cnblogs.com/csnd/p/12062896.html