博客
关于我
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中怎样设置指定ip远程访问连接
查看>>
mysql中数据表的基本操作很难嘛,由这个实验来带你从头走一遍
查看>>
Mysql中文乱码问题完美解决方案
查看>>
mysql中的 +号 和 CONCAT(str1,str2,...)
查看>>
Mysql中的 IFNULL 函数的详解
查看>>
mysql中的collate关键字是什么意思?
查看>>
MySql中的concat()相关函数
查看>>
mysql中的concat函数,concat_ws函数,concat_group函数之间的区别
查看>>
MySQL中的count函数
查看>>
MySQL中的DB、DBMS、SQL
查看>>
MySQL中的DECIMAL类型:MYSQL_TYPE_DECIMAL与MYSQL_TYPE_NEWDECIMAL详解
查看>>
MySQL中的GROUP_CONCAT()函数详解与实战应用
查看>>
MySQL中的IO问题分析与优化
查看>>
MySQL中的ON DUPLICATE KEY UPDATE详解与应用
查看>>
mysql中的rbs,SharePoint RBS:即使启用了RBS,内容数据库也在不断增长
查看>>
mysql中的undo log、redo log 、binlog大致概要
查看>>
Mysql中的using
查看>>
MySQL中的关键字深入比较:UNION vs UNION ALL
查看>>
mysql中的四大运算符种类汇总20多项,用了三天三夜来整理的,还不赶快收藏
查看>>
mysql中的字段如何选择合适的数据类型呢?
查看>>