HDU 5775 L - Bubble Sort 树状数组

给定一段冒泡排序的代码,要求输出每个数字能到达的最右边的位置和最左边的位置的差

因为那段冒泡排序的代码是每次选取一个最小的数,放在左边的,所以,每个数最多能到达右边的位置应该是起始位置i+右边有多少个数比它大。

它能到达的最左的位置,可以这样考虑

1、它本来应该是排去起始位置的左边的,就是它本来是一个小的数字,起始位置在末尾这种情况的话。最左边的值就是a[i]

2、它是去右边的,那么最左边的值就是起始位置,

两种取max就去可以了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
typedef unsigned long long int ULL;
#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000  +20;
int a[maxn];
int c[maxn];
int n;
int dpR_min[maxn];
int ans[maxn];
int pos[maxn];
int f;
int lowbit (int x)//得到x二进制末尾0的个数的2次方 2^num
{
    return x&(-x);
}
void add (int pos,int val)//在第pos位加上val这个值
{
    while (pos<=n) //n是元素的个数
    {
        c[pos] += val;        pos += lowbit(pos);
    }
    return ;
}
int get_sum (int pos) //求解:1--pos的总和
{
    int ans = 0;
    while (pos)
    {
        ans += c[pos];        pos -= lowbit(pos);
    }
    return ans;
}

void work ()
{
    scanf("%d",&n);
    for (int i=1; i<=n; ++i)
    {
        scanf("%d",&a[i]);
        pos[a[i]]=i;
    }
    memset(c,0,sizeof c);
    for (int i=n; i>=1; --i)
    {
        dpR_min[i] = get_sum(a[i]-1);
        add(a[i],1);
    }
    for (int i=1;i<=n;++i)
    {
        int end = pos[a[i]] + dpR_min[pos[a[i]]];//看看它最右能去哪里
        //如果这个数字是要去右边
        int tR = end - pos[a[i]];
        //去左边
        int tL = end - a[i];
        ans[a[i]] = max(tR,tL);
    }
    printf ("Case #%d:",++f);
    for (int i=1;i<=n;++i)
    {
        printf (" %d",ans[i]);
    }
    printf ("\n");
}

int main()
{
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    scanf("%d",&t);
    while (t--) work();
    return 0;
}
View Code

 

题目要看懂。。题目看得我头疼

posted on 2016-08-22 21:07  stupid_one  阅读(235)  评论(0编辑  收藏  举报

导航