HDU 5122 K.Bro Sorting

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5122


题意:告诉你一种排序方法是随机选择一个数,然后不停的向后交换,直到它后面的数不比它小,这样算一次。给出一个序列,问将其升序排好最少需要几次。


思路:我们每次将当前最大的数拿到最后面,这样是最优的。所以我们每次只需要判断第i个数需不需要移动,需要移动答案就加一。假设当前操作到了第k大的数,那么k就是最大的,比k大的数都拿到后面去排好序了,所以我们只需要看看原序列中比k小且位置在k之前的数是不是k-1个,就知道k需不需要移动了。用一个树状数组维护一下前缀和,将原序列扫一遍,对于数a[i],先把a[i]加到树状数组里,再查询一下[1,a[i]-1]区间内的个数是否为a[i]-1个来更新答案。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007

const int maxn = 1000001;

int sum[maxn+10];
int a[maxn+10];
int T,n;

int lowbit(int x)
{
    return x&(-x);
}

void add(int x)
{
    while( x <= maxn )
    {
        sum[x]++;
        x+=lowbit(x);
    }
}

int query(int x)
{
    int ans = 0;
    while( x > 0 )
    {
        ans+=sum[x];
        x-=lowbit(x);
    }
    return ans;
}

void init()
{
    scanf("%d",&n);
    Clean(sum,0);
    rep(i,1,n)
    {
        scanf("%d",&a[i]);
    }
}

int solve()
{
    int ans = 0;
    rep(i,1,n)
    {
        add( a[i] );
        if ( query( a[i] - 1 ) != a[i] - 1 ) ans++;
    }
    return ans;
}

int main()
{
    cin>>T;
    rep(kase,1,T)
    {
        init();
        printf("Case #%d: %d\n",kase,solve());
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值