题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=6318

Problem Description
Long long ago, there was an integer sequence a.
Tonyfang think this sequence is messy, so he will count the number of inversions in this sequence. Because he is angry, you will have to pay x yuan for every inversion in the sequence.
You don't want to pay too much, so you can try to play some tricks before he sees this sequence. You can pay y yuan to swap any two adjacent elements.
What is the minimum amount of money you need to spend?
The definition of inversion in this problem is pair (i,j) which 1≤i<j≤n and ai>aj.
 
Input
There are multiple test cases, please read till the end of input file.
For each test, in the first line, three integers, n,x,y, n represents the length of the sequence.
In the second line, n integers separated by spaces, representing the orginal sequence a.
1≤n,x,y≤100000, numbers in the sequence are in [−1e9,1e9]. There're 10 test cases.
 
Output
For every test case, a single integer representing minimum money to pay.
 
Sample Input
3 233 666
1 2 3
3 1 666
3 2 1
 
Sample Output
0
3

题意:

给出n个元素的序列,现在你有机会,花费y元交换一次任意相邻两个元素,交换完毕后,若存在逆序对,每一个逆序对要花费x元,求最少的花费。

题解:

考虑冒泡排序:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。做完一遍,最后的元素是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个(因为确定是最大的)。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

显然,我们每交换一次两个相邻元素,就必然能使逆序数减1,而排序完毕后逆序数等于0,所以冒泡排序交换相邻元素次数等于逆序数。

而且同样易知,我们不可能用更少的交换次数使得逆序数等于0。

所以我们就得到了如下结论:

  逆序数 = 在只能交换相邻元素条件下,使得序列有序的最少交换次数

而本题中,交换一次花费x,一个逆序对花费y,也就是说,要么全部交换直到没有逆序对,要么一次也不交换。

所以我们只要求出逆序数k,答案ans = k * min(x,y)。

由于本题数值范围[-1e9,1e9],而n最多1e5,树状数组不可能开2e9,所以只能进行离散化。

时间复杂度:sort函数O(nlogn),unique函数O(n),暴力枚举n个元素并获取ID以及树状数组修改+查询操作O(nlogn),总的O(nlogn),满足要求。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=+; struct _BIT //单点修改、区间查询
{
int n,C[maxn];
int lowbit(int x){return x&(-x);}
void init(int n)
{
this->n=n;
memset(C,,sizeof(C));
}
void add(int pos,int val) //在pos点加上val
{
while(pos<=n)
{
C[pos]+=val;
pos+=lowbit(pos);
}
}
int ask(int pos) //查询1~pos点的和
{
int ret=;
while(pos>)
{
ret+=C[pos];
pos-=lowbit(pos);
}
return ret;
}
}BIT; int n;
ll x,y; int a[maxn]; vector<int> v;
inline int getID(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+;}
int main()
{
while(scanf("%d%d%d",&n,&x,&y)!=EOF)
{
v.clear();
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
v.push_back(a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end()); BIT.init(v.size());
ll cnt=;
for(int i=;i<=n;i++)
{
int id=getID(a[i]);
BIT.add(id,);
cnt+=BIT.ask(v.size())-BIT.ask(id);
} cout<<cnt*min(x,y)<<endl;
}
}

HDU 6318 - Swaps and Inversions - [离散化+树状数组求逆序数][杭电2018多校赛2]的更多相关文章

  1. SGU180 Inversions(树状数组求逆序数)

    题目: 思路:先离散化数据然后树状数组搞一下求逆序数. 离散化的方法:https://blog.csdn.net/gokou_ruri/article/details/7723378 自己对用树状数组 ...

  2. hdu 1394 Minimum Inversion Number (裸树状数组 求逆序数 && 归并排序求逆序数)

    题目链接 题意: 给一个n个数的序列a1, a2, ..., an ,这些数的范围是0-n-1, 可以把前面m个数移动到后面去,形成新序列:a1, a2, ..., an-1, an (where m ...

  3. 牛客练习赛38 D 题 出题人的手环 (离散化+树状数组求逆序对+前缀和)

    链接:https://ac.nowcoder.com/acm/contest/358/D来源:牛客网 出题人的手环 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他 ...

  4. hdu 5147 Sequence II (树状数组 求逆序数)

    题目链接 Sequence II Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. poj 2299 Ultra-QuickSort(树状数组求逆序数)

    链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...

  6. HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number                         ...

  7. poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)

    题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...

  8. Codeforces645B【树状数组求逆序数】

    题意: 给你1-n的序列,然后有k次机会的操作,每一次你可以选择两个数交换. 求一个最大的逆序数. 思路: 感觉就是最后一个和第一个交换,然后往中间逼近,到最终的序列,用树状数组求一下逆序数. #in ...

  9. HDU 1394 Minimum Inversion Number(线段树/树状数组求逆序数)

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

随机推荐

  1. [Object Tracking] Identify and Track Specific Object

    Abstract—Augmented Reality (AR) has become increasingly popular in recent years and it has a widespr ...

  2. Git初级使用教程

    什么是 Git? Git 是一款免费的.开源的.分布式的版本控制系统.旨在快速高效地处理无论规模大小的任何软件工程. 每一个 Git克隆 都是一个完整的文件库,含有全部历史记录和修订追踪能力,不依赖于 ...

  3. ECharts 3 -- gauge表盘的配置项

    绘制一个简单的表盘图表 在绘图前我们需要为 ECharts 准备一个具备高宽的 DOM 容器. <body> <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM --& ...

  4. 处理特殊格式的GET传参

    有群友问 这样的传参格式如何接受获取 xx.php?con="one"=>5,"two"=>0,"three"=>1 那么 ...

  5. error:undefined reference to 'net_message_processor::net_message_processor()'

    net_message_processor是我自己定义的一个类,文件名称分别是net_message_processor.h  & net_message_processor.cpp 和CCD ...

  6. Docker应用之容器

    容器是独立运行的一个或一组应用,以及他们的运行态环境 1.启动容器(基于镜像新建一个容器并启动或将终止状态的容器重新启动) run后面添加--name参数可以指定容器的名称,否则系统默认会给名称:使用 ...

  7. thinkphp3.2 实现二级导航和高亮显示

    一.控制器代码如下: public function index(){ //高亮显示 $action = CONTROLLER_NAME."/".ACTION_NAME; $thi ...

  8. sklearn提供的自带的数据集

    sklearn 的数据集有好多个种 自带的小数据集(packaged dataset):sklearn.datasets.load_<name> 可在线下载的数据集(Downloaded ...

  9. JUnit(>4.0)@BeforeClass、@Before、@Test、@After、@AfterClass、@Ignore

    JUnit 4 开始使用 Java 5 中的注解(annotation),常用的几个 annotation 介绍: @BeforeClass:针对所有测试,只执行一次,且必须为static void ...

  10. 记录一次OOM排查经历(一)

    一.经历概要 程序里有个跑数据的job,这个job的主要功能是往数据库写假数据. 既需要跑历史数据(传给job的日期是过去的时间),也需要能够上线后,实时跑(十秒钟触发一次,传入触发时的当前时间). ...