hdu2838Cow Sorting(树状数组+逆序数)

题目链接:点击打开链接

题意描述:给定一个长度为100000的数组,每个元素范围在1~100000,且互不相同,交换其中的任意两个数需要花费的代价为两个数之和。问如何交换使数组有序,花费的代价最小?

解题思路:

1、显然我们知道,要使一个数组有序至少交换的次数(即必须要交换的次数)为数组中的逆序数

2、由于数组的长度比较大所以我们可以通过树状数组来统计结果

此处需要两个树状数组

第一个:记录小于等于某个值的元素的个数

第二个:记录小于等于某个值的元素的和

代码:

#include <cstdio>
#include <cstring>
#define MAXN 100010
using namespace std;
int C[MAXN];

int lowbit(int x)
{
    return x&(-x);
}
int sum(int pos)
{
    int ret=0;
    while(pos>0)
    {
        ret+=C[pos];
        pos-=lowbit(pos);
    }
    return ret;
}
void add(int pos,int v)
{
    while(pos<=100000)
    {
        C[pos]+=v;
        pos+=lowbit(pos);
    }
}
long long Ct[MAXN];
long long sumt(int pos)
{
    long long ret=0;
    while(pos>0)
    {
        ret+=Ct[pos];
        pos-=lowbit(pos);
    }
    return ret;
}
void addt(int pos,int v)
{
    while(pos<=100000)
    {
        Ct[pos]+=v;
        pos+=lowbit(pos);
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(C,0,sizeof(C));
        memset(Ct,0,sizeof(Ct));
        long long ans=0;
        int x;
        for(int i=0; i<n; ++i)
        {
            scanf("%d",&x);
            add(x,1);
            addt(x,x);
            ans+=((sum(100000)-sum(x))*(long long)x+sumt(100000)-sumt(x));///注意溢出问题
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-12 23:57:23

hdu2838Cow Sorting(树状数组+逆序数)的相关文章

hdu2838Cow Sorting树状数组求逆序对

//对于数列中的一个数,在它前面比它大的一定要和它交换 //在它后面比它小的一定得和它交换 //可以用树状数组存入每一个数在它之前比它小的数的个数 //那么(i-1)-total[i]为在它前面比它大的数的个数 //然后在所有数都存入树状数组后用getsum(num[i])可以求出整个数列中比这个数小的数的个数 //那么getsum(num[i])-1-total[i]则为在它之后比它小的数的个数 //ans+=num[i]*(i-2+getsum(num[i])-2*total[i]); #i

HDU 4911 (树状数组+逆序数)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4911 题目大意:最多可以交换K次,就最小逆序对数 解题思路: 逆序数定理,当逆序对数大于0时,若ak<ak+1,那么交换后逆序对数+1,反之-1. 设原始序列最小逆序对数=cnt 那么,交换K次的最小逆序对数max(0,cnt-k) 在求原始序列最小逆序对数上,朴素暴力复杂度O(n^2)不可取 有以下两种O(nlogn)的方法: ①排序内计算: 主要是利用归并排序内的特性,即相邻两个归并序列逆序情

树状数组+逆序数与顺序数——HDU 2492

对应HDU题目:点击打开链接 Ping pong Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description N(3N20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skil

HDU5196--DZY Loves Inversions 树状数组 逆序数

题意查询给定[L, R]区间内 逆序对数 ==k的子区间的个数. 我们只需要求出 子区间小于等于k的个数和小于等于k-1的个数,然后相减就得出答案了. 对于i(1≤i≤n),我们计算ri表示[i,ri]的逆序对数小于等于K,且ri的值最大.(ri对应代码中的cnt数组) 显然ri单调不降,我们可以通过用两个指针扫一遍,利用树状数组计算出r数组. 对于每个询问L,R,我们要计算的是∑i=LR[min(R,ri)−i+1] 由于ri具有单调性,那我们直接在上面二分即可,然后记一个前缀和(s数组).

HDU - 2838 Cow Sorting (树状数组 + 逆序对)

HDU - 2838 Cow Sorting Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Description Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" lev

POJ3067 树状数组+逆序数

设两线段为(x1,y1) ,(x2,y2), 若使两线段相交,需使x1<x2&&y1>y2||x1>x2&&y1<y2. 那么本题就变得很简单了,对东边点x从小到大排序,当x相等时对西边点y从小到大排序,每插入一条线段,就求一下逆序对数.总和即为答案. 代码如下: 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define

HDU Cow Sorting (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2838 Cow Sorting 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 cow

hdu 5193 分块 树状数组 逆序对

题意: 给出n个数,a1,a2,a3,...,an,给出m个修改,每个修改往数组的某个位置后面插入一个数,或者把某个位置上的数移除.求每次修改后逆序对的个数. 限制: 1 <= n,m <= 20000; 1 <= ai <= n 思路: 插入和删除用分块来处理,块与块之间用双向链表来维护,每一块用树状数组来求小于某个数的数有多少个. 外层可以使用分块维护下标,这样添加和删除元素的时候,也很方便,直接暴力.查找权值个数时,使用树状数组比较方便.内层通过树状数组维护权值. 每次更新即

HDU5122 K.Bro Sorting 树状数组类逆序数应用

题意很简单,看案例就能懂,一个长度为n的序列,要重新排序,升序,每一次拿这个数跟后面所有数比较,需要移动尽可能往后面移动,问需要操作几次 对案例进行分析,从后往前面判,若发现前面有比当前这个数大的数答案就加1,但是发现后面很难讨论清楚,还得正向来分析,当前这个数,若后面有数字比它小,那就肯定需要操作一次的,由此想到了树状数组求逆序数中的一个操作,树状数组求逆序数就是需要先求出当前树状数组里面有多少个数比当前这个数小,于是想到了,把这个数组里的数字从后面往前面 一个一个加进树状数组里,每加一个,就