HDU - 5775 - Bubble Sort(树状数组 & 线段树 & 逆序 & 思维)

HDU - 5775 - Bubble Sort


Bubble Sort

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.
题目链接

题目的意思就是要你求冒泡排序前后和过程中每一个数字能够到达的最左端和最右端的差值。
刚开始没有读懂题目,就直接求了每一个数的逆序,结果WA了。
根据冒泡排序的话,基本思想就是消除逆序,每一次都把后面小的数移动到前面,由于是从1到N的冒泡排序,所以第一次一定是把1移到第一位,第二次把2移到第二位,以此类推。我们模拟一下冒泡排序的过程的话就会发现,小的一直往前移动,这样的话大的数也就被迫挤到了后面从而消除了一次逆序,这样的话,一个数能到达的最右端就要看他右面有几个的比他小的,也就是右面有几个逆序对。一个数字被作为最大数字的时候只会被往后移动,从而把所有逆序都消除,也同时到达了最右端,如果该位置不是这个数正确的位置,那么这个数将被作为比较小的数字向前移动,那么就看最左端了,向左移动完之后一定是在它的排好序的位置,然后在于他的起始位置比较,取一个最小值即是最左端的位置。然后两数做差。


树状数组AC代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int maxn=1001000;
int n;
int c[maxn], a[maxn];
int ans[maxn];

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

void update(int pos, int val)
{
    while(pos < maxn)
    {
        c[pos] += val;
        pos += lowbit(pos);
    }
}

int query(int pos)
{
    ll sum = 0;
    while(pos > 0)
    {
        sum += c[pos];
        pos -= lowbit(pos);
    }
    return sum;
}
int main()
{
    int t;
    scanf("%d", &t);
    for(int test = 1; test <= t; test++)
    {
        scanf("%d", &n);
        int temp;
        memset(c, 0, sizeof(c));
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        for(int i = n; i >= 1; i--)
        {
            int k = query(a[i] - 1);
            update(a[i], 1);
            ans[a[i]] = i + k - min(a[i], i);
        }
        printf("Case #%d: ", test);
        for (int i = 1; i < n; i++) printf("%d ", ans[i]);
        printf("%d\n", ans[n]);
    }
    return 0;
}

线段树AC代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 1e6 + 5;
int a[maxn], ans[maxn];

struct node
{
    int l, r, val;
}p[maxn];

void build(int l, int r, int cur)
{
    p[cur].l = l, p[cur].r = r;
    p[cur].val = 0;
    if(l == r)  return ;
    int m = (l + r) >> 1;
    build(l, m, cur << 1);
    build(m + 1, r, cur << 1 | 1);
}

void pushup(int cur)
{
    p[cur].val = p[cur << 1].val + p[cur << 1 | 1].val;
}

void update(int pos, int val, int cur)
{
    int l = p[cur].l, r = p[cur].r;
    if(l == r)
    {
        p[cur].val = val;
        return ;
    }
    int m = (l + r) >> 1;
    if(pos <= m)    update(pos, val, cur << 1);
    if(pos > m) update(pos, val, cur << 1 | 1);
    pushup(cur);
}

int query(int ll, int rr, int cur)
{
    int res = 0;
    int l = p[cur].l, r = p[cur].r;
    if(ll <= l && r <= rr)  return p[cur].val;
    int m = (l + r) >> 1;
    if(ll <= m) res += query(ll, rr, cur << 1);
    if(rr > m)  res += query(ll, rr, cur << 1 | 1);
    return res;
}

int main()
{
    int t, n;
    scanf("%d", &t);
    for(int test = 1; test <= t; test++)
    {
        scanf("%d", &n);
        build(1, n, 1);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i = n; i >= 1; i--)
        {
            int k = query(1, a[i] - 1, 1);
            update(a[i], 1, 1);
            ans[a[i]] = i + k - min(a[i], i);
        }
        printf("Case #%d: ", test);
        for(int i = 1; i < n; i++)  printf("%d ", ans[i]);
        printf("%d\n", ans[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40788897/article/details/81583753