• 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
    ",sum(loc[t]-1));
                update(loc[t],-1);
    		}
    		else{
    			t=n-(i/2)+1;
                printf("%d
    ",sum(n)-sum(loc[t]));
                update(loc[t],-1);
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    前端开发 —— 快速入门:JavaScript & CSS 脚手架
    MySQL全方位练习(学生表 教师表 课程表 分数表)
    php判断是爬虫在访问还是用户浏览器在访问
    Eclipse 安装Activiti插件
    随机生成一串字符串(java)
    js文字转语音(speechSynthesis)
    语音识别(Web Speech API)
    js判断是否为手机端访问
    tomcat部署安全证书文件(阿里云SSL证书)
    springboot文字转语音(jacob)
  • 原文地址:https://www.cnblogs.com/znk161223/p/11517393.html
Copyright © 2020-2023  润新知