小陶与杠铃片

题目描述

小陶在举重队负责后勤工作。举重队的训练场中有一个区域一排码放了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;
}
相关推荐
代码改善世界1 天前
【数据结构与算法】栈和队列题解
数据结构
ShineWinsu1 天前
对于C++:继承的解析—上
开发语言·数据结构·c++·算法·面试·笔试·继承
消失的旧时光-19431 天前
C++ 多线程与并发系统取向(二)—— 资源保护:std::mutex 与 RAII(类比 Java synchronized)
java·开发语言·c++·并发
抓饼先生1 天前
iceoryx编译和验证
linux·c++·零拷贝·iceoryx
王老师青少年编程1 天前
2020年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第2题)
c++·题解·真题·初赛·信奥赛·csp-s·提高组
你的冰西瓜1 天前
C++ STL算法——排序和相关操作
开发语言·c++·算法·stl
今儿敲了吗1 天前
29| 高考志愿
c++·笔记·学习·算法
浅念-1 天前
C++ 模板进阶
开发语言·数据结构·c++·经验分享·笔记·学习·模版
紫陌涵光1 天前
77. 组合
c++·算法·leetcode·深度优先
We་ct1 天前
LeetCode 222. 完全二叉树的节点个数:两种解法详解(BFS + 二分查找优化)
数据结构·算法·leetcode·typescript