博客
关于我
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_secure_installation初始化数据库报Access denied
查看>>
MySQL_西安11月销售昨日未上架的产品_20161212
查看>>
Mysql——深入浅出InnoDB底层原理
查看>>
MySQL“被动”性能优化汇总
查看>>
MySQL、HBase 和 Elasticsearch:特点与区别详解
查看>>
MySQL、Redis高频面试题汇总
查看>>
MYSQL、SQL Server、Oracle数据库排序空值null问题及其解决办法
查看>>
mysql一个字段为空时使用另一个字段排序
查看>>
MySQL一个表A中多个字段关联了表B的ID,如何关联查询?
查看>>
MYSQL一直显示正在启动
查看>>
MySQL一站到底!华为首发MySQL进阶宝典,基础+优化+源码+架构+实战五飞
查看>>
MySQL万字总结!超详细!
查看>>
Mysql下载以及安装(新手入门,超详细)
查看>>
MySQL不会性能调优?看看这份清华架构师编写的MySQL性能优化手册吧
查看>>
MySQL不同字符集及排序规则详解:业务场景下的最佳选
查看>>
Mysql不同官方版本对比
查看>>
MySQL与Informix数据库中的同义表创建:深入解析与比较
查看>>
mysql与mem_细说 MySQL 之 MEM_ROOT
查看>>
MySQL与Oracle的数据迁移注意事项,另附转换工具链接
查看>>
mysql丢失更新问题
查看>>