Day7 T2 排序

题目

你收到一项对数组进行排序的任务,数组中是1到N个一个排列。你突然想出以下一种特别的排序方法,分为以下N个阶段:
•阶段1,把数字1通过每次交换相邻两个数移到位置1;
•阶段2,用同样的方法把N移到位置N;
•阶段3,把数字2移到位置2处;
•阶段4,把数字N-1移到位置N-1处;
•依此类推。
换句话说,如果当前阶段为奇数,则把最小的未操作的数移到正确位置上,如果阶段为偶数,则把最大的未操作的数移到正确位置上。
写一个程序,给出初始的排列情况,计算每一阶段交换的次数。

输入

第一行包含一个整数N(1 \(\leqslant\) N \(\leqslant\) 100000),表示数组中元素的个数。
接下来N行每行一个整数描述初始的排列情况。

输出

输出每一阶段的交换次数。

样例

输出 输入
3
2
1
3
1
0
0
5
5
4
3
2
1
4
3
2
1
0
7
5
4
3
7
1
2
6
4
2
3
0
2
1
0

题解

听说这题和用树状数组求逆序对很像,但是……本蒟蒻不会用树状数组求逆序对QAQ我求逆序对都是用的归并排序qwq
记录每个数对应的位置,每个数需要交换的次数就是它前面没有排好序的数的个数,那么我们用1对应没有排好序的数,0对应排好了序的数,用树状数组求和即可。

#include<bits/stdc++.h>
using namespace std;
int n;
int c[100010],loc[100010];

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

void update(int x,int y){
    for(;x<=n;x+=lowbit(x)) c[x]+=y;
}

int sum(int x){
    int res=0;
    for(;x;x-=lowbit(x)) res+=c[x];
    return res;
}

int main(){
    scanf("%d",&n);
    int temp;
    for(register int i=1;i<=n;i++){
        scanf("%d",&temp);
        loc[temp]=i;
        update(i,1);
    }
    for(register int i=1;i<=n;i++){
        int t;
        if(i&1){
            t=(i+1)/2;
            printf("%d\n",sum(loc[t]-1));
            update(loc[t],-1);
        }
        else{
            t=n-(i/2)+1;
            printf("%d\n",sum(n)-sum(loc[t]));
            update(loc[t],-1);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/znk161223/p/11517393.html