HDU 5775 Bubble Sort (树状数组或线段树)

来源:互联网 发布:网络监控能看到多久的 编辑:程序博客网 时间:2024/05/17 16:15

题解:

考虑一个位置上的数字c在冒泡排序过程的变化情况。c会被其后面比c小的数字各交换一次,之后c就会只向前移动。数组从右向左扫,树状数组维护一下得到每个值右边有多少个比其小的值,加上原位置得到最右位置,最左位置为初始位置和最终位置的最小值。

分析出这个结果应该不难,现在要做的就是如何在nlogn的时间里求出每个值右边有多少个比其小的值;比赛的时候队友用线段树做的。我现在再用树状数组写了一遍。其实原理都是一样的:

比如序列 3 4 5 2 1 

新设一个数组c[ ] ,初始为 0 0 0 0 0

然后从右向左遍历序列 5 4 3 2 1 ;对c进行如下操作:

第一次:c变为 1 0 0 0 0 

第二次:1 1 0 0 0

第三次:1 1 0 0 1

第四次:1 1 0 1 1

第五次:1 1 1 1 1

同时,每对c操作一次,就统计i这个位置前1的数量,这个数量即为 i 右边比其小的数的个数;

树状数组详解

/* ***********************************************Author        :angon************************************************ */#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <stack>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define REP(i,k,n) for(int i=k;i<n;i++)#define REPP(i,k,n) for(int i=k;i<=n;i++)#define scan(d) scanf("%d",&d)#define scann(n,m) scanf("%d%d",&n,&m)#define mst(a,k)  memset(a,k,sizeof(a));#define LL long long#define maxn 1005#define mod 100000007/*inline int read(){    int s=0;    char ch=getchar();    for(; ch<'0'||ch>'9'; ch=getchar());    for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';    return s;}inline void print(int x){    if(!x)return;    print(x/10);    putchar(x%10+'0');}*/struct node{    int v,id;}p[100005];int n,c[100005];int lowbit(int x){    return x & (-x);}void modify(int x,int add){    while(x<=n)    {        c[x]+=add;        x+=lowbit(x);    }}int get_sum(int x){    int ret=0;    while(x>0)    {        ret+=c[x];        x-=lowbit(x);    }    return ret;}int r[100005];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t;    scan(t);    REPP(cas,1,t)    {        scan(n);        REPP(i,1,n)        {            scan(p[i].v); p[p[i].v].id=i;        }        mst(c,0);        for(int i=n;i>0;i--)        {            modify(p[i].v,1);            r[p[i].v] = i + get_sum(p[i].v)-1;        }        printf("Case #%d: ",cas);        for(int i=1;i<=n;i++)        {            int ans = abs(r[i] - (int)min(p[i].id , i));            printf("%d%c",ans,i<n?' ':'\n');        }    }    return 0;}


0 0
原创粉丝点击