逆序对(hdu2838)
来源:互联网 发布:ov7670 51单片机引脚图 编辑:程序博客网 时间:2024/06/03 01:16
题目概述:
给定一个序列,交换其中两个元素x,y的代价是x+y,求将一个序列变成单调不减的序列的最小代价。
题目思路:
把一个小的从后面移到前面,需要和前面所有比他大的交换,而大的移到后面则需要和后面所有比他小的交换。所以就是正着求一次每个数在当前序列的位置和倒着求一次。最后乘这个元素然后加到结果里。
当然其实就是求逆序对数,用线段树,用类似归并排序,用树状数组都可以。。。。
给定一个序列,交换其中两个元素x,y的代价是x+y,求将一个序列变成单调不减的序列的最小代价。
题目思路:
把一个小的从后面移到前面,需要和前面所有比他大的交换,而大的移到后面则需要和后面所有比他小的交换。所以就是正着求一次每个数在当前序列的位置和倒着求一次。最后乘这个元素然后加到结果里。
当然其实就是求逆序对数,用线段树,用类似归并排序,用树状数组都可以。。。。
一开始想用treap写的,不过左旋和右旋大数据的时候老是RE,所以果断将其退化成二叉搜索树。
代码:
#include<iostream>#include<cstdlib>#include<cstdio>#include<time.h>using namespace std;struct treap{ treap *l,*r; int v,f,s; inline int ls() { return l?l->s:0; } inline int rs() { return r?r->s:0; }};int a[100010];treap* treapinsert(treap *a,int v){ if (!a) { a=(treap*)malloc(sizeof(treap)); a->v=v; a->f=rand(); a->l=0; a->r=0; a->s=1; } else if (v<=a->v) { a->s++; a->l=treapinsert(a->l,v); } else { a->s++; a->r=treapinsert(a->r,v); } return a;}int treaprank(treap *a,int v,int cur){ if (a&&v==a->v) return a->ls()+cur+1; else if (a&&v<=a->v) return treaprank(a->l,v,cur); else if (a) return treaprank(a->r,v,cur+a->ls()+1); else return 0;}int main(){ srand(time(0)); int n; cin>>n; for (int i=1;i<=n;i++) scanf("%d",&a[i]); long long ans=0; treap *root=0; for (int i=1;i<=n;i++) { root=treapinsert(root,a[i]); ans+=(long long)a[i]*(i-treaprank(root,a[i],0)); } free(root); treap *rooot=0; for (int i=n;i>=1;i--) { rooot=treapinsert(rooot,a[i]); ans+=(long long)a[i]*(treaprank(rooot,a[i],0)-1); } free(rooot); cout<<ans<<endl;}
0 0
- 逆序对(hdu2838)
- HDU2838(树状数组求逆序数)
- 树状数组专题(八)hdu2838计算逆序数
- HDU2838 Cow Sorting (逆序数+求和)
- HDU2838 Cow Sorting【树状数组】【逆序数】
- hdu2838
- hdu2838
- 归并方法求逆序对(洛谷1908逆序对)
- HDOJ-1394(逆序对)
- 逆序对 (归并排序)
- 逆序对问题(归并)
- POJ1804 Brainman (逆序对)
- 区间平均值(逆序对)
- 蓝桥杯-逆序对(java)
- 卡片游戏(逆序对)
- 区间平均值(逆序对)
- (洛谷 1908)逆序对
- 逆序数 & 逆序对
- Cable Master
- Android中EditText控件的几种使用方法
- 统计电话(poj 1002)
- 捡骨头(hdu2602)
- 金币(hdu1114)
- 逆序对(hdu2838)
- 开关
- 采药
- 彩色项链
- 阿凡提的烦恼
- 敌兵布阵
- 第k极值
- CSS 实现图片灰度效果 兼容各种浏览器
- 划分数