HDU 5775 Bubble Sort(冒泡排序的位置变换)

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

Problem Description
P is a permutation of the integers from 1 to N(index starting from 1).
Here is the code of Bubble Sort in C++.

for(int i=1;i<=N;++i)
for(int j=N,t;j>i;—j)
if(P[j-1] > P[j])
t=P[j],P[j]=P[j-1],P[j-1]=t;

After the sort, the array is in increasing order. ?? wants to know the absolute values of difference of rightmost place and leftmost place for every number it reached.

Input
The first line of the input gives the number of test cases T; T test cases follow.
Each consists of one line with one integer N, followed by another line with a permutation of the integers from 1 to N, inclusive.

limits
T <= 20
1 <= N <= 100000
N is larger than 10000 in only one case.

Output
For each test case output “Case #x: y1 y2 … yN” (without quotes), where x is the test case number (starting from 1), and yi is the difference of rightmost place and leftmost place of number i.

Sample Input
2
3
3 1 2
3
1 2 3

Sample Output
Case #1: 1 1 2
Case #2: 0 0 0

Hint
In first case, (3, 1, 2) -> (3, 1, 2) -> (1, 3, 2) -> (1, 2, 3)
the leftmost place and rightmost place of 1 is 1 and 2, 2 is 2 and 3, 3 is 1 and 3
In second case, the array has already in increasing order. So the answer of every number is 0.

这道题的意思是,给你冒泡排序的代码,根据这个代码模拟一遍,然后输出每个数字到达的最左边和最右边的的差的绝对值。

这道题,其实有点坑,因为他题目里面说,只有一组数据是超过10^5的,所以当时做的时候就想,是不是可以两个for循环,然后,成功超时~

后来想到的是,如果一个数字比他的位置的值要大,那么,他肯定会向后移动,反之,如果他的值比他的位置要小,那么这个数字就要向前移动,这样,就已经可以确定一边了。

而另外一边就和逆序数有关了。因为那个数字的后面有多少个数字比他小,他就要向后移动多少位,而逆序数求的是在他的前面有多少个比他大的,知道了前面有多少位比他大的,比如a[i],那么n-a[i]就是比 a[i] 大的数目,所以(n-a[i])-逆序数就是后面的比 a[i] 大的数目。而n-i就是a[i]后面有多少个数字,所以n-i-[(n-a[i])-逆序数]就是在a[i]后面,并且比a[i]小的数的个数了。而n-i-[(n-a[i])-逆序数]等价于a[i]+逆序数-i。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#define maxn 100010
#define maxm 1000010
using namespace std;
int T,n,cas;
int num[2*maxn];
int f[2*maxn];
int ans[2*maxn];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x)
{
    while(x<=n)
    {
        f[x]++;
        x+=lowbit(x);
    }
}
int get_sum(int x)
{
    int t=0;
    while(x!=0)
    {
        t+=f[x];
        x-=lowbit(x);
    }
    return t;
}
int main()
{
    scanf("%d",&T);
    cas=0;
    while(T--)
    {
        memset(f,0,sizeof(f));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)  scanf("%d",&num[i]);
        int cnt=0;
        int l=0;
        int r=0;
        int nx=0;
        int xiao=0;
        for(int i=1;i<=n;i++)
        {
            update(num[i]);
            nx=i-get_sum(num[i]);
            xiao=num[i]+nx-i;
            l=min(i,num[i]);
            r=max(i,i+xiao);
            ans[num[i]]=abs(r-l);
        }
        printf("Case #%d:",++cas);
        for(int i=1;i<=n;i++)  printf(" %d",ans[i]);
        printf("\n"); 
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值