小陶与杠铃片

题目描述

小陶在举重队负责后勤工作。举重队的训练场中有一个区域一排码放了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;
}
相关推荐
CoderCodingNo2 小时前
【GESP】C++四级/五级练习题 luogu-P1223 排队接水
开发语言·c++·算法
云深处@2 小时前
【C++】AVL树
数据结构
sycmancia2 小时前
C++进阶01——示例
开发语言·c++
CoderCodingNo2 小时前
【GESP】C++五级/四级练习题 luogu-P1413 坚果保龄球
开发语言·c++·算法
Yvonne爱编码3 小时前
JAVA数据结构 DAY4-ArrayList
java·开发语言·数据结构
阿猿收手吧!3 小时前
【C++】C++原子操作:compare_exchange_weak详解
java·jvm·c++
Trouvaille ~3 小时前
【Linux】网络编程基础(二):数据封装与网络传输流程
linux·运维·服务器·网络·c++·tcp/ip·通信
2301_822366353 小时前
C++中的命令模式变体
开发语言·c++·算法
每天要多喝水3 小时前
nlohmann/json 的使用
c++·json