HDU 6318.Swaps and Inversions-求逆序对-线段树 or 归并排序 or 离散化+树状数组 (2018 Multi-University Training Contest 2 1010)
6318.Swaps and Inversions
这个题就是找逆序对,然后逆序对数*min(x,y)就可以了。
官方题解:注意到逆序对=交换相邻需要交换的次数,那么输出 逆序对个数 即可。
求逆序对有4种操作,线段树 、BIT、归并排序、树状数组。
我敲了线段树、归并排序和树状数组版的。
关于这几种方法求逆序对,自行百度吧,懒了。。。
代码(线段树版-注意排序):
//1010-找逆序对数-线段树求逆序对数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const double eps=1e-;
const int maxn=1e5+;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[maxn<<]; void PushUp(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];
} void build(int l,int r,int rt)
{
sum[rt]=;
if(l==r){
return ;
} int m=(l+r)>>;
build(lson);
build(rson);
PushUp(rt);
} void update(int p,int l,int r,int rt)
{
if(l==r){
sum[rt]++;
return ;
} int m=(l+r)>>;
if(p<=m)update(p,lson);
else update(p,rson);
PushUp(rt);
} ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R){
return sum[rt];
}
int m=(l+r)>>;
ll ret=;
if(L<=m) ret+=query(L,R,lson);
if(R> m) ret+=query(L,R,rson);
return ret;
} int a[maxn],b[maxn];
int main()
{
int n,x,y;
while(~scanf("%d%d%d",&n,&x,&y)){
build(,n,);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+,b+n+);
int len=unique(b+,b+n+)-b-;
for(int i=;i<=n;i++){
a[i]=upper_bound(b+,b+len+,a[i])-b-;
} ll sum=;
for(int i=;i<=n;i++){
sum+=query(a[i]+,n,,n,);
update(a[i],,n,);
}
printf("%lld\n",sum*min(x,y));
}
return ;
}
代码(归并排序版):
//1010-6318-求逆序对数-归并排序
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<cassert>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
const int inf=0x3f3f3f3f; int a[maxn],tmp[maxn];
ll ans; void Merge(int l,int m,int r)
{
int i=l;
int j=m+;
int k=l;
while(i<=m&&j<=r){
if(a[i]>a[j]){
tmp[k++]=a[j++];
ans+=m-i+;
}
else{
tmp[k++]=a[i++];
}
}
while(i<=m) tmp[k++]=a[i++];
while(j<=r) tmp[k++]=a[j++];
for(int i=l;i<=r;i++)
a[i]=tmp[i];
} void Merge_sort(int l,int r)
{
if(l<r){
int m=(l+r)>>;
Merge_sort(l,m);
Merge_sort(m+,r);
Merge(l,m,r);
}
} int main()
{
int n,x,y;
while(~scanf("%d%d%d",&n,&x,&y)){
memset(a,,sizeof(a));
memset(tmp,,sizeof(tmp));
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
ans=;
Merge_sort(,n);
printf("%lld\n",ans*min(x,y));
}
}
可以去看一下ACdreamer的博客。
代码(离散化+树状数组):
//1010-6318-求逆序对-离散化+树状数组版
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<cassert>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+; int tree[maxn];
int n; int lowbit(int x)
{
return x&(-x);
} void update(int x,int val)
{
for(int i=x;i<=n;i+=lowbit(i)){
tree[i]+=val;
}
} ll getsum(int x)
{
ll ans=;
for(int i=x;i>;i-=lowbit(i)){
ans+=tree[i];
}
return ans;
} int a[maxn],b[maxn];
map<int,int> mp; int main()
{
int x,y;
while(~scanf("%d%d%d",&n,&x,&y)){
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+,b++n);
int num=;
mp.clear();
for(int i=;i<=n;i++)
mp[b[i]]=num++;
for(int i=;i<=n;i++)
a[i]=mp[a[i]];
memset(tree,,sizeof(tree));
ll ans=;
for(int i=n;i>;i--){
ans+=getsum(a[i]-);
update(a[i],);
}
printf("%lld\n",ans*min(x,y));
}
return ;
}
就这样吧,溜了。
啊啊啊啊,cf又掉分了༼༎ຶᴗ༎ຶ༽
HDU 6318.Swaps and Inversions-求逆序对-线段树 or 归并排序 or 离散化+树状数组 (2018 Multi-University Training Contest 2 1010)的更多相关文章
- HDU 6318 - Swaps and Inversions - [离散化+树状数组求逆序数][杭电2018多校赛2]
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=6318 Problem Description Long long ago, there was an ...
- hdu 6318 Swaps and Inversions (线段树求逆序对数)
Swaps and Inversions Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- HDU 6318 Swaps and Inversions 思路很巧妙!!!(转换为树状数组或者归并求解逆序数)
Swaps and Inversions Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- HDU 6318 Swaps and Inversions(归并排序 || 树状数组)题解
题意:一个逆序对罚钱x元,现在给你交换的机会,每交换任意相邻两个数花钱y,问你最少付多少钱 思路:最近在补之前还没过的题,发现了这道多校的题.显然,交换相邻两个数逆序对必然会变化+1或者-1,那我们肯 ...
- [HDU 6318] Swaps and Inversions
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6318 [算法] 线段树 / 树状数组 [代码] #include<bits/stdc++.h ...
- 【a703】求逆序对(线段树的解法)
Time Limit: 10 second Memory Limit: 2 MB 问题描述 给定一个序列a1,a2...an.如果存在i小于j 并且ai大于aj,那么我们称之为逆序对,求给定序列中逆序 ...
- 归并排序(归并排序求逆序对数)--16--归并排序--Leetcode面试题51.数组中的逆序对
面试题51. 数组中的逆序对 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 示例 1: 输入: [7,5,6,4] 输出 ...
- poj2299树状数组入门,求逆序对
今天入门了树状数组 习题链接 https://blog.csdn.net/liuqiyao_01/article/details/26963913 离散化数据:用一个数组来记录每个值在数列中的排名,不 ...
- codeforces 459D D. Pashmak and Parmida's problem(离散化+线段树或树状数组求逆序对)
题目链接: D. Pashmak and Parmida's problem time limit per test 3 seconds memory limit per test 256 megab ...
随机推荐
- 当xml结构很深时候 可以通过父节点删除子元素
当xml结构很深时候 可以通过父节点删除子元素
- 洛谷 P2801 教主的魔法 解题报告
P2801 教主的魔法 题目描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.--.N. ...
- 什么是node.js的事件驱动编程
Node.js现在非常活跃,相关生态社区已经超过Lua(基本上比较知名的功能都有nodejs模块实现).但是我们为何要使用Node.Js?相比传统的webserver服务模式,nodejs有什么优点优 ...
- CodeIgniter自带的数据库类使用介绍
在 CodeIgniter 中,使用数据库是非常频繁的事情.你可以使用框架自带的数据库类,就能便捷地进行数据库操作. 初始化数据库类 依据你的数据库配置载入并初始化数据库类: view source ...
- Mybatis LIKE模糊查询
1.在代码中拼接好字符串后传入进来 2.使用CONCAT在xml中拼接字符串: <if test="queryParam.keyword != null"> AND b ...
- TCP ------ keep-alive - 判断TCP链路的连接情况
TCP 是面向连接的 , 在实际应用中通常都需要检测对端是否还处于连接中.如果已断开连接,主要分为以下几种情况: 1. 连接的对端正常关闭,即使用 closesocket 关闭连接 ...
- 480000 millis timeout while waiting for channel to be ready for write异常处理
2014-08-25 15:35:05,691 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: DatanodeRegistration( ...
- iOS 单元测试(Unit Test 和 UI Test)
之前一直搞过~~最近试了一下下,完美~~ 附上一篇文章,不同的伙伴可以看看: http://www.jianshu.com/p/009844a0b9edUnitTest(简单的单元测试使用) http ...
- 【数据结构】bzoj1651专用牛棚
Description Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will onl ...
- loj6029 「雅礼集训 2017 Day1」市场
传送门:https://loj.ac/problem/6029 [题解] 考虑如果有一些近似连续的段 比如 2 2 2 3 3 3,考虑在除3意义下,变成0 0 0 1 1 1,相当于整体-2 又:区 ...