博客
关于我
2018HDU多校2-1010-Swaps and Inversions(hdu 6318)-逆序数,树状数组
阅读量:281 次
发布时间:2019-03-01

本文共 1373 字,大约阅读时间需要 4 分钟。

这里写图片描述

题意:

给出一个数列,其中每有一个逆序数就花费x元,也可以花费y元交换相邻两个数,求处理这个数列的最小花费

思路:

可分析出,交换一次最多只能减少一个逆序数,所以只可能全部交换或者一个都不交换,故此题只需求出逆序数个数即可

O(nlogn)时间下求逆序数个数,可用归并排序法或树状数组法
使用树状数组求解,先将数列从大到小排序,每次选取最大的数放入,树状数组中记录某位置出现数的个数(某位置是否有数),因选取的是最大的数,若最大数位置之前的位置有其他数的话,一定小于最大数,即有逆序数

代码:

#include 
#include
#include
using namespace std;const int N=100050;int n;long long c[N]; //c[n]表示a[1~n]的和,a数组省略struct node{ int val,pos;}a[100005];int lowbit(int x) //求2^k{ return x & -x;}long long getsum(int n) //区间查询,求a[1~n]的和{ long long res = 0; while(n>0) { res+=c[n]; n=n-lowbit(n); } return res;}int change(int x) //单点更新,将c[x]的值加1{ while(x<=n) { c[x]++; x+=lowbit(x); }}bool cmp(node a,node b) //包含相同数{ if(a.val!=b.val) return a.val>b.val; return a.pos>b.pos;}int main(){ std::ios::sync_with_stdio(false); int x,y; while(cin>>n>>x>>y) { memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { cin>>a[i].val; a[i].pos=i; } sort(a+1,a+n+1,cmp); long long cnt=0; for(int i=1;i<=n;i++) { change(a[i].pos); //修改最大数位置的值 cnt+=getsum(a[i].pos-1); //最大数位置之前的所有位置和,即区间求和,可知比当前数小的数有多少个 } long long ans1=cnt*x; long long ans2=cnt*y; cout<
<
你可能感兴趣的文章
Mysql 整形列的字节与存储范围
查看>>
mysql 断电数据损坏,无法启动
查看>>
MySQL 日期时间类型的选择
查看>>
Mysql 时间操作(当天,昨天,7天,30天,半年,全年,季度)
查看>>
MySQL 是如何加锁的?
查看>>
MySQL 是怎样运行的 - InnoDB数据页结构
查看>>
mysql 更新子表_mysql 在update中实现子查询的方式
查看>>
MySQL 有什么优点?
查看>>
mysql 权限整理记录
查看>>
mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
查看>>
MYSQL 查看最大连接数和修改最大连接数
查看>>
MySQL 查看有哪些表
查看>>
mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
查看>>
MySql 查询以逗号分隔的字符串的方法(正则)
查看>>
MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
查看>>
mysql 查询数据库所有表的字段信息
查看>>
【Java基础】什么是面向对象?
查看>>
mysql 查询,正数降序排序,负数升序排序
查看>>
MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
查看>>
mysql 死锁 Deadlock found when trying to get lock; try restarting transaction
查看>>