HDU 6318 - Swaps and Inversions - [离散化+树状数组求逆序数][杭电2018多校赛2]
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=6318
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.
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.
题意:
给出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]的更多相关文章
- SGU180 Inversions(树状数组求逆序数)
题目: 思路:先离散化数据然后树状数组搞一下求逆序数. 离散化的方法:https://blog.csdn.net/gokou_ruri/article/details/7723378 自己对用树状数组 ...
- hdu 1394 Minimum Inversion Number (裸树状数组 求逆序数 && 归并排序求逆序数)
题目链接 题意: 给一个n个数的序列a1, a2, ..., an ,这些数的范围是0-n-1, 可以把前面m个数移动到后面去,形成新序列:a1, a2, ..., an-1, an (where m ...
- 牛客练习赛38 D 题 出题人的手环 (离散化+树状数组求逆序对+前缀和)
链接:https://ac.nowcoder.com/acm/contest/358/D来源:牛客网 出题人的手环 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他 ...
- hdu 5147 Sequence II (树状数组 求逆序数)
题目链接 Sequence II Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数)
链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...
- HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...
- Codeforces645B【树状数组求逆序数】
题意: 给你1-n的序列,然后有k次机会的操作,每一次你可以选择两个数交换. 求一个最大的逆序数. 思路: 感觉就是最后一个和第一个交换,然后往中间逼近,到最终的序列,用树状数组求一下逆序数. #in ...
- HDU 1394 Minimum Inversion Number(线段树/树状数组求逆序数)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java ...
随机推荐
- 手机APP支付--整合银联支付控件
长话短说,本文根据银联官方说明文档,简单总结下,并且说明下中途碰到问题该如何解决. 一.开发前的准备工作1. 打开https://open.unionpay.com/,后续说的文档下载.FAQ查询等都 ...
- Extjs定义的Fckeditor控件
Ext.namespace('CRM.Panels'); //Ext.BoxComponent 这里继承是参考的Ext.form.Field CRM.Panels.Fckeditor = Ext.ex ...
- SELECT中常用的子查询操作
MySQL中的子查询 是在MySQL中经常使用到的一个操作,不仅仅是用在DQL语句中,在DDL语句.DML语句中也都会常用到子查询. 子查询的定义: 子查询是将一个查询语句嵌套在另一个查询语句中: 在 ...
- List中的Contains方法内部其实是用对象的equals方法做比较,所以如果比较两个类就重写类的equals方法即可;而Set是调用equals和hashCode
public class Person { private String name; private int age; public String getName() { return name; } ...
- mysql类型对应Java的类型
整型 JDBCtinyint java.lang.Integersmallintmediumint java.lang.Longint bigint ...
- U3D调用7z解压文件
using UnityEngine; using System; using System.IO; using System.Diagnostics; public class Test : Mono ...
- 阿里云CentOS7挂载SSD云盘的方法
https://bbs.aliyun.com/read/151152.html 阿里云购买的第2块云盘默认是不自动挂载的,需要手动配置挂载上. 1.查看SSD云盘 sudo fdisk -l Disk ...
- #pragma init_seg
先进后出原则,最先初始化的最后析构! 1.C++中全局对象.变量的构造函数调用顺序是跟声明有一定关系的,即在同一个文件中先声明的先调用.对于不同文件中的全局对象.变量,它们的构造函数调用顺序是未定义的 ...
- WIN32编程经验总结
一 窗口和消息 1. 前缀: 2 WPARAM和LPARAM的意义在Windows是一种16位系统时,WndProc的第三个参数被定义为WORD,是一个16位的无符号整数,而第四个参数被定义为一个LO ...
- Oracle和Mysql中mybatis模糊匹配查询区别
1.Oracle AND NAME LIKE '%'||#{name}||'%' 2.Mysql AND NAME LIKE "%"#{name}"%"