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);    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 两岁宝宝吃什么吐什么怎么办 7岁宝宝吃多了吐怎么办 7个月的宝宝大便干燥怎么办 10个月宝宝便秘大便干燥怎么办 一岁半宝宝老是拉糊糊状大便怎么办 外阴部长了一个疙瘩有点痒怎么办 小孩打架被另一个小孩家人告怎么办 德保豆浆机有电但不工作怎么办 刚买的笔记本c盘不足怎么办 qq糖粘在喉咙气管里怎么办 穿上旗袍后感觉后腰处不平整怎么办 机打票给客人给错联怎么办?急 ps修证件照感觉不太立体怎么办 手机百度上下载的文档打不开怎么办 5岁宝宝乘飞机没带证件怎么办 网上订飞机票忘记订儿童票了怎么办 两岁宝宝对牛奶鸡蛋过敏了怎么办 两岁宝宝坐不住好跑怎么办 宝宝两岁多了不愿意坐小马桶怎么办 坐火车小孩拉屎在被子上怎么办 川航飞机票名字错了一个字怎么办 胜战本领怎么看走向战场怎么办 数数字油画你的颜料干了怎么办? 数字油画涂颜料涂错了怎么办 绝地求生模拟器注册已达上限怎么办 孕妇把番茄和虾一起吃了怎么办 4岁宝贝吃了玩具小电池怎么办 微信使用零钱需完善实名信息怎么办 两岁宝宝刷牙不会吐水怎么办 孩子牙龈上长了小牙怎么办 供暖公司未供暖却收取供暖费怎么办 两岁宝宝认知和语言能力低怎么办 蜡笔同步被对方发现删掉的怎么办 微信时间和手机时间不同步怎么办 孩子们家乡爱画美丽的也自己怎么办 娃把豆豆弄进鼻孔了怎么办 20岁了不知道自己该干什么怎么办 遇到一个新手买家恶意拍下怎么办 淘宝卖螃蟹有什么要求美工怎么办 淘宝衣服吊牌剪了想退货怎么办修 用图片在淘宝搜衣服搜不到怎么办