hdu2838
2016-05-19 17:19
232 查看
http://acm.hdu.edu.cn/showproblem.php?pid=2838
题意 n个数的排列,每次可以互换相邻的元素,最终变成一个递增的序列,每次互换的代价为互换的两个数的和,求最小代价。
每次处理前i个,也就是顺序处理就是最小,假如第i个数为a[i],那么需要的代价为a[i]*c+sum(a[i]),c是a[i]前比a[i]大的数的个数,sum(a[i])是a[i]前比a[i]大的数的和,用树状数组,两个数组,一个存个数,一个存和
题意 n个数的排列,每次可以互换相邻的元素,最终变成一个递增的序列,每次互换的代价为互换的两个数的和,求最小代价。
每次处理前i个,也就是顺序处理就是最小,假如第i个数为a[i],那么需要的代价为a[i]*c+sum(a[i]),c是a[i]前比a[i]大的数的个数,sum(a[i])是a[i]前比a[i]大的数的和,用树状数组,两个数组,一个存个数,一个存和
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; const int maxn=100010; ll a[maxn]; ll b[maxn],c[maxn];//b是比a[i]小的个数,c是比a[i]小的数的和 int n; ll lowbit(ll x) { return x&-x; } ll sum_b(ll x) { ll ret=0; while(x>0) { ret+=b[x]; x-=lowbit(x); } return ret; } ll sum_c(ll x) { ll ret=0; while(x>0) { ret+=c[x]; x-=lowbit(x); } return ret; } void update(int i,int j) { while(i<=n) { b[i]+=1; c[i]+=j; i+=lowbit(i); } } int main() { while(scanf("%d",&n)!=-1) { long long ans=0,cnt=0; memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); update(a[i],a[i]); cnt+=a[i]; ans+=a[i]*(i-sum_b(a[i])); ans+=cnt-sum_c(a[i]); } printf("%lld\n",ans); } return 0; }
相关文章推荐
- 定制标记---标记文件
- linux使用小记
- 语音及音频相关
- 【特效】隔行变色
- 蘑菇街购物车动态添加
- Android学习笔记三十一:Java异常处理中try,catch,finally的各种组合用法
- linux 下问题处理
- YARN与MRv1的对比
- 基础总结篇之三:Activity的task相关
- MFC CListCtrl的方法
- ReactNative动画(下)
- Android audio transmit with Base64 based on XMPP
- 以栈解决迷宫问题
- mac下mysql workbench导出数据库
- 着色器文件中的 Properties 定义
- 第12周项目1--实现复数类中的运算重载(1)
- 将博客搬至CSDN
- 作为一名工作了5年的菜鸟程序员开始了博客生涯
- 集合类与容器
- MySql-如何查询删除数据表重复记录