HDU2838(树状数组求逆序数)
来源:互联网 发布:paxos算法论文 编辑:程序博客网 时间:2024/05/19 23:05
参考博客:http://blog.csdn.net/u011721440/article/details/38067787
Cow Sorting
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3567 Accepted Submission(s): 1242
Problem Description
Sherlock’s N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cow has a unique “grumpiness” level in the range 1…100,000. Since grumpy cows are more likely to damage Sherlock’s milking equipment, Sherlock would like to reorder the cows in line so they are lined up in increasing order of grumpiness. During this process, the places of any two cows (necessarily adjacent) can be interchanged. Since grumpy cows are harder to move, it takes Sherlock a total of X + Y units of time to exchange two cows whose grumpiness levels are X and Y.
Please help Sherlock calculate the minimal time required to reorder the cows.
Input
Line 1: A single integer: N
Lines 2..N + 1: Each line contains a single integer: line i + 1 describes the grumpiness of cow i.
Output
Line 1: A single line with the minimal time required to reorder the cows in increasing order of grumpiness.
Sample Input
3
2
3
1
Sample Output
7
Hint
Input Details
Three cows are standing in line with respective grumpiness levels 2, 3, and 1.
Output Details
2 3 1 : Initial order.
2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4).
1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).
题意:给你1~n的打乱的数,让你重新排序,但是只能相邻的更改,更改的代价就是两数之和,求最小代价。这其实就是逆序数。
逆序数:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。(百度百科)我找到的网友解释更简单理解:
1、跟标准列相反序数的总和
比如说
标准列是1 2 3 4 5
那么 5 4 3 2 1 的逆序数算法:
看第二个,4之前有一个5,在标准列中5在4的后面,所以记1个
类似的,第三个 3 之前有 4 5 都是在标准列中3的后面,所以记2个
同样的,2 之前有3个,1之前有4个
将这些数加起来就是逆序数=1+2+3+4=10
再举一个 2 4 3 1 5
4 之前有0个
3 之前有1个
1 之前有3个
5 之前有0个
所以逆序数就是1+3=4
这个个题要开俩数组,一个是c(保存数字的个数),另一个是s(保存总和)。理解逆序数以后就可以把求价值的公式写出来:比当前大的数的个数*当前数+比当前数大的总和
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn=100005;int a[maxn],c[maxn];//c保存数的出现long long s[maxn];int n;int lowbit(int k){ return k&(-k);}void add(int x)//建立{ int d=x; while(x<=n) { c[x]++;//保存个数 s[x]+=d;//存总和 x+=lowbit(x); }}int sum1(int x)//一定要先想树状数组的原理,求出比当前数小的个数,总数相减就可以得到大的数{ int sum=0; while(x) { sum+=c[x]; x-=lowbit(x); } return sum;}long long sum2(int x)//求比当前值大的和{ long long sum=0; while(x) { sum+=s[x]; x-=lowbit(x); } return sum;}int main(){ while(~scanf("%d",&n)) { memset(c,0,sizeof(c)); memset(s,0,sizeof(s)); int k,t; long long ans=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); add(a[i]); k=sum1(a[i]); t=i-k; if(t!=0) { ans+=(long long)a[i]*t; ans+=sum2(n)-sum2(a[i]);//在for遍历时,每次输入的值是当前值,而sum2(n)是当前总和,因为还没有输入完 } } printf("%lld\n",ans); }}
- HDU2838(树状数组求逆序数)
- 树状数组专题(八)hdu2838计算逆序数
- HDU2838 Cow Sorting【树状数组】【逆序数】
- 树状数组求逆序数(模板)
- poj3067(树状数组求逆序数)
- NYOJ 求逆序数(树状数组)
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组 求逆序数
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组 求逆序数
- 树状数组求逆序数
- PAT B1029. 旧键盘
- 计算机网络总结
- 一个全面详细的gulp工作流
- Ordering Tasks(拓扑排序)
- c++中map的使用方法(一)
- HDU2838(树状数组求逆序数)
- R语言-环境系统
- leetcode 485. Max Consecutive Ones
- 百练_4044:小白鼠再排队
- NOI2017 退役记
- PS
- SpringMVC —— @RequestParam @RequestBody @PathVariable 等参数绑定
- mycat分布式mysql中间件(分片规则)
- C语言阶乘level1.0