小陶与杠铃片

题目描述

小陶在举重队负责后勤工作。举重队的训练场中有一个区域一排码放了n片杠铃片,每天运动员们训练完之后会将杠铃片放回,之后小陶需要重新整理杠铃片的顺序,使它们由轻到重依次排好。由于杠铃片很重,小陶每次只能选两片相邻的杠铃片,交换它们的位置。现在小陶想知道,这一天他至少需要交换多少次才能整理完毕?

已知n<=200000,0<=杠铃片重量<=200000。

输入格式

第一行一个正整数n,表示有n片杠铃片;

第二行n个整数,表示运动员们放回后每片杠铃片依次的重量。

输出格式

输出一个整数,表示小陶至少交换的次数。

样例

【样例输入】

复制代码
10
16808 75250 50074 143659 108931 11273 27545 50879 177924 37710

【样例输出】

复制代码
20
数据范围与提示

对于30%的数据: n<=5000 对于60%的数据:

n<=30000 对于100%的数据:

n<=200000,0<=杠铃片重量<=200000

一些想法

这道题依旧用树状数组做,这道题其实就是求冒泡排序的交换次数,也就是求有多少对逆序对。

简单来说,就是找一个数前面有多少个数比他大,然后将个数全部加起来,就得到要交换的次数了。是一种前缀查询,所以用树状数组做最好。

先定义一个树状数组用于储存前缀和(小于当前重量元素的数量)。然后主函数部分:因为输入数有可能是 0,所以要整体偏移加 1(避免死循环),然后答案累加已处理的数的数量( i-1 )减小于当前重量的元素个数,也就是累加要交换的次数(已处理个数减小于当前重量的元素个数,剩下的就是在当前数前面但大于当前数的元素个数,也就是要交换的次数),这里要用到查询小于当前数的元素个数(查询函数)。然后将当前数放进树状数组里,为后续查询提供数据。这就要用到修改数组。而这两个自定义数组都要用 lowbit 数组来划分区间。

函数部分,有三个自定义函数:

lowbit 函数:用位运算找 x 二进制的最后一个 1 。树状数组的所有操作都基于 lowbit 实现区间划分。

查询函数:查询 比 x 小的元素个数(前缀和查询),然后只要 x 大于 0(没有超出范围),然后将 x 不断减小(减自己的lowbit),跳转到前一个区间,将个数增加。(简单来说就是分解,将当前区间不断分解成多个小区间)。

修改函数:将第 x 个数增加 y ,因为前面的点有变化,所以包含这个点的在范围内的所有数都要跟着变化,因为父节点要随着子节点的变化而变化,所以每次增加自己的 lowbit ,也就是不断往后一个区间,直到达到边界,然后每一个区间都增加指定值。

注意:统计交换次数的数组要开 long long!!!

因为测试数据会很大,如果不开 long long 会出现越界行为,导致程序崩溃或答案错误。

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,c[200005],x;
long long sum=0;
const int N=200020;
int lowbit(int x){
	return x&-x;
}
int zs(int x){
	int cnt=0;
	for(;x>0;x-=lowbit(x)){
		cnt+=c[x];
	}
	return cnt;
}
void sm(int x,int y){
	for(;x<N;x+=lowbit(x)){
		c[x]+=y;
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x;
		x++;
		sum+=(i-1)-zs(x);
		sm(x,1);
	}
	cout<<sum;
	return 0;
}
相关推荐
想做小南娘,发现自己是女生喵8 小时前
【无标题】
数据结构·算法
旖-旎10 小时前
《LeetCode647 回文子串 || LeetCode 5 最长回文子串》
c++·算法·leetcode·动态规划·哈希算法
Darkwanderor11 小时前
对Linux的进程控制的研究
linux·运维·c++
云泽80811 小时前
从零吃透 C++ 异常:抛出捕获、栈展开、异常重抛与编码规范详解
开发语言·c++·代码规范
REDcker12 小时前
libdatachannel 快速入门
c++·webrtc·datachannel
凤凰院凶涛QAQ13 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
second6013 小时前
第一部分:快速上手 —— 建立 C++ 基本语法与编程范式
开发语言·c++
郝学胜-神的一滴13 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
Irissgwe14 小时前
算法滑动窗口
数据结构·算法
bksczm14 小时前
linux之线程概念和控制
linux·开发语言·c++