HDU

来源:互联网 发布:it软件设计师 编辑:程序博客网 时间:2024/05/17 07:04

Inversion

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 5238    Accepted Submission(s): 1839


Problem Description
bobo has a sequence a1,a2,…,an. 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 ai>aj.
 

Input
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).
 

Output
For each tests:

A single integer denotes the minimum number of inversions.
 

Sample Input
3 12 2 13 02 2 1
 

Sample Output
12
 

Author
Xiaoxu Guo (ftiasch)
 

Source
2014 Multi-University Training Contest 5 
 


题意:求将一串连续的序列交换不超过k次后,该序列的逆序对数最少为多少,交换只能两个相邻的数互相交换位置


交换两相邻数,序列中的逆序对总数+1或-1,取决于两个数谁比较大,因为要使得最小,所以每次交换我们都要使其-1,所以答案就是max(0,初始逆序对数-k)

问题就转换为求初始逆序对数,这个可以用树状数组区间求和来解决,不过数的范围较大(≤1e9)所以要对数进行离散化一下


#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#define LL long longusing namespace std;const int N = 1e5+10;int n,k,a[N],su[N];int low(int x){return x&-x;}void add(int x){    for(;x<=n;x+=low(x)) su[x]++;}LL Sum(int x){    int ans = 0;    for(;x>0;x-=low(x)) ans += su[x];    return ans;}int Rank[N],Rn;void SetRank(){    Rn = n;    sort(Rank+1,Rank+Rn+1);    int I = 1;    for(int i=2;i<=Rn;i++) if(Rank[i-1]!=Rank[i]) Rank[++I] =        Rank[i];    Rn = I;}int GetRank(int pos){    int L=1,R=Rn,M=(L+R)>>1;    while(L<=R)    {        M=(L+R)>>1;        if(Rank[M]<pos) L = M+1;        else if(Rank[M]>pos) R = M-1;        else return M;    }    return M;}int main(){    while(scanf("%d%d",&n,&k)!=EOF){        LL sum = 0;        memset(su,0,sizeof su);        memset(Rank,0,sizeof Rank);        for(int i=1;i<=n;i++) {            scanf("%d",&a[i]);            Rank[i] = a[i];        }        SetRank();        for(int i=1;i<=n;i++){            int pos = GetRank(a[i]);            sum += Sum(n) - Sum(pos);            add(pos);        }        printf("%lld\n",sum-k<0?0:sum-k);    }    return 0;}



原创粉丝点击