hdu 2838 树状数组求逆序数及交换位置产生移动的数的和

本文介绍了一个经典的排序问题CowSorting,该问题要求将一系列具有不同“暴躁”级别的奶牛按升序重新排列,每次只能交换相邻的两个奶牛,并且交换成本等于两个奶牛暴躁值之和。文章详细解释了问题背景、输入输出格式及示例,并提供了一种基于树状数组的数据结构解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Cow Sorting

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1600    Accepted Submission(s): 507


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).
 

Source
 
  题意:给你N个排列不规则的数,任务是把它从小到大排好,每次只能交换相邻两个数,交换一次的代价为两数之和,求最小代价

注意    每次交换 都必须只能交换相邻的2个 

思路:对于当前数X,我们如果知道前面比它大的数有多少,假设为K,那么有部分代价是确定的,那就是K*X;然后还得加上比它大的那些数之和,这就是当数列到X为止,排好所需要的最小代价。

注意本题不能用long  long  必须用__int64  坑!

#include<stdio.h>
#include<string.h>
#define ll __int64
ll c[100000+5],v[100000+5];
int n;
int Lowbit(int k)
{
    return (k&-k);
}
void update(int pos,int num,int val)
{
    while(pos<=n)
    {
        c[pos]+=num;
        v[pos]+=val;
        pos+=Lowbit(pos);
    }
}
ll sum_count(int pos)
{
    ll  s=0;

    while(pos>0)
    {
        s+=c[pos];
        pos-=Lowbit(pos);
    }
    return s;
}
ll sum(int pos)
{
    ll s=0;

    while(pos>0)
    {
        s+=v[pos];
        pos-=Lowbit(pos);
    }
    return s;
}
int main()
{
    int i,x;
    while(scanf("%d",&n)!=-1)
    {
        memset(c,0,sizeof(c));
        memset(v,0,sizeof(v));
        ll ans=0,k2,k1;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&x);
            update(x,1,x);
            k1=i-sum_count(x);///到此为止  比x大的个数;
///sum_count[x] 为输入i个数的时候 x之前有sum_count[x]个比x小的数 用i相减则为大于x的个数
            if(k1!=0)
            {
            k2=sum(n)-sum(x);///到此为止  比x大的数的和;
            ans+=x*k1+k2;///到此为止 比x大的数与x交换之后的和;
            }
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


 

 

参考  http://blog.csdn.net/me4546/article/details/6333225
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值