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 ...
随机推荐
- 基于oracle的sql(结构化查询语言)指令
创建表空间 create tablespace 表空间名 datafile '存储路径(c:\a\a.dbf)' size 200m autoextend on next 10m maxsize un ...
- POJ1511:Invitation Cards(最短路)
Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 34743 Accepted: 114 ...
- Codeforces Round #510 (Div. 2) D. Petya and Array(树状数组)
D. Petya and Array 题目链接:https://codeforces.com/contest/1042/problem/D 题意: 给出n个数,问一共有多少个区间,满足区间和小于t. ...
- HDU3038:How Many Answers Are Wrong(带权并查集)
How Many Answers Are Wrong Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- 生日蛋糕 POJ - 1190
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱.当 ...
- Extend the size of ext3 partition online in VM
1. Increase disk space in vCenter 2. scan disk on the Linux VM # fdisk -lu > /tmp/fdisk. # > / ...
- jw player笔记二----修改logo
一.修改HTML5模式下的logo 见http://blog.csdn.net/xiong_mao_1/article/details/17222757 二.修改FLASH模式下的logo IE7/8 ...
- [Python]安装完pip、pygame后,仍然import pygame报错
按照<python编程从入门到实践>上的教程下载了pygame的whl文件进行安装, 在cmd窗口里import pygame提示无错误,在IDEL里程序也能正常运行, 但是pycharm ...
- C#中file类的应用
现在就其中几个常用的进行介绍: Create:一般使用此重载方法,File.Create (String) ,String是一个路径名,表示文件的完整路径,返回值是一个FileStream实例: Co ...
- 知问前端——日历UI(二)
datapicker外观选项 属性 默认值/类型 说明 disabled false/布尔值 禁用日历 numberOfMonths 1/数值 日历中同时显示的月份个数.默认为1,如果设置3就同时显示 ...