2016 Multi-University Training Contest 4 1012 Bubble Sort (线段树)

来源:互联网 发布:程序员需要看的书 编辑:程序博客网 时间:2024/06/09 20:38

题意

给出一个序列,问在冒泡排序的过程中,每个数到达的最左和最优位置之差是多少。

思路

观察发现,根据题目给的算法,每个数的最左位置就是他的最终位置,最右位置是他的初始位置加上他右边所有比他小的数的个数,因为这些数会先被换到他的左侧。所以只用统计每个数右边比他小的数的个数就行了,这里我用的是线段树的办法。

代码

#include <bits/stdc++.h>using namespace std;const int maxn = 1e5+10;/*-------------------------------------*/#define max(a,b) (a>b)?a:b#define min(a,b) (a>b)?b:a#define lson l , m , rt << 1#define rson m + 1 , r , rt << 1 | 1int idx[maxn];int num[maxn];int sum[maxn << 2];void pushup(int rt){    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];}void update(int id,int l, int r, int rt){    if (l==r){        sum[rt] = 1;        return ;    }    int m = (l+r) >>1;    if (id <= m) {       update(id, lson);    }    if (m < id) {        update(id, rson);    }    pushup(rt);}int query(int L, int R, int l, int r, int rt){    if (L <= l && r <= R){        return sum[rt];    }    int m = (l + r) >> 1;    int ret = 0;    if (L <= m) {        ret += query(L , R , lson);    }    if (m < R) {        ret += query(L , R , rson);    }    return ret;}/*----------------------------------*/int main(){    int T,n,kas = 1;    cin >> T;    while(T --){        memset(sum, 0, sizeof(sum));        scanf("%d", &n);        for (int i = 1; i <= n; i++){            scanf("%d", &num[i]);            idx[num[i]] = i;        }        printf("Case #%d:", kas++);        for (int i = 1; i <= n; i++){            int l = min(idx[i], i);            int r = max(i, idx[i] + query(idx[i], n,1,n,1));            update(idx[i], 1, n, 1);            printf(" %d", r - l);        }        puts("");    }}
0 0
原创粉丝点击