洛谷 P6186 [NOI Online #1 提高组]冒泡排序 树状数组

P6186 [NOI Online #1 提高组]冒泡排序

题目链接
(题解里的大佬写的真好!连我都能看懂
这道题是给一个排列,有两种操作:
1 x 把x 与 x + 1交换
2 x 问执行x次以后冒泡以后,有多少个逆序对。很显然x >= n - 1时 答案 == 0
先来看看执行一次冒泡排序后是什么样子?
原数组:3 2 1 6 5 4 7 9 8
执行一次:2 1 3 5 4 6 7 8 9
因为冒泡嘛,就是选当前最大的往后移,然后把最大值移到后面,所以对于一个数再执行一次冒泡操作时,如果他前面至少有一个比他大的,他在这次操作中一定不会动。所以一次操作可以把他前面没有比他大的数移动到后面比他大的第一个数的位置。这很显然。。 可能说的不清楚
再来看看一次移动对逆序对数量的贡献:因为把大的往后移,逆序对数量肯定减少,减少了n - 他前面没有比他大的数的数量
因为例如3 2 1 6 5 4 7 9 8 这个数组,
3 2 1这部分由于3的移动会减少两个逆序对。
6 5 4会由于6的移动减少两个逆序对
7这部分不会移动
9 8这部分会减少1个逆序对。
而部分与部分之间的逆序对数量不会变。
所以可以想象一下后面,每轮移动都会减少n - 他前面没有比他大的数的数量,设a[i] 表示(前面比他大的数量小于等于 i )的数的数量,那么进行x轮答案就是逆序对的数量 -(n - a[1])- (n - a[1] - a[2]) ……
所以就很简单了,,用树状数组维护a的前缀和就好了。。
好绕啊,我写了些什么。。
代码:

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
/** Init-Start*/
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define pb push_back
#define mkp make_pair
#define st first
#define sd second
const int maxn = 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值