HDU6318 Swaps and Inversions

Swaps and Inversions

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


 

Problem Description

Long long ago, there was an integer sequence a.
Tonyfang think this sequence is messy, so he will count the number of inversions in this sequence. Because he is angry, you will have to pay x yuan for every inversion in the sequence.
You don't want to pay too much, so you can try to play some tricks before he sees this sequence. You can pay y yuan to swap any two adjacent elements.
What is the minimum amount of money you need to spend?
The definition of inversion in this problem is pair (i,j) which 1≤i<j≤n and ai>aj.

 

Input

There are multiple test cases, please read till the end of input file.
For each test, in the first line, three integers, n,x,y, n represents the length of the sequence.
In the second line, n integers separated by spaces, representing the orginal sequence a.
1≤n,x,y≤100000, numbers in the sequence are in [−109,109]. There're 10 test cases.

 

Output

For every test case, a single integer representing minimum money to pay.

 

Sample Input

 

3 233 666 1 2 3 3 1 666 3 2 1

 

Sample Output

 

0 3

原地址在这里

题意:

在这里会给你三个数,一个N,一个X,一个Y,然后N表示这有一个序列为N的长度,有人来检查,这个序列如果有不是从小到大顺序的,有一个就罚X元,然后你不想花费太多,于是就可以在检查之前对序列进行操作,这个操作只能对相邻两个数进行一次交换,交换一次就是Y元,然后要你求最少花费。一开始想到了求逆序数,后面起岔路..........如果我修改某一些数,这样就是修改的钱,加上罚的钱,会不会少一点...............后面发现,不会,你如果这里X减少,那么就会让Y增多,而如果Y比X大,那么花费的钱就会更多,所以就是直接算逆序数,然后乘以其中少的花费..................

算法:

这题的算法主要就是求逆序数,求逆序数,你可以用树状数组或者归并排序或者一个一个数,当然你一个一个数,T是常态,还有一种是线段树,这几种都可以求,然后:

ans = min(sum*x,sum*y);

输出ans就行了。。。。。

这里附上我觉得较好的逆序数求法讲解:

树状数组求逆序数:

较容易理解的

说的好的,理解需要一定能力

总的解说:

在这里

代码:

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;

const int maxn = 1e5+5;
int tree[maxn<<2],b[maxn];
long long n,x,y;

struct node
{
    int k,i;
    bool operator < (const node &a) const
    {
        if(k != a.k) return k < a.k;
        return i < a.i;
    }
}p[maxn];

void add(int k,int num)
{
    while(k <= n) tree[k] += num , k += k&(-k);
}

int query(int k)
{
    int sum = 0;
    while(k) sum += tree[k] , k -= k&(-k);
    return sum;
}

int main()
{
    while(scanf("%d%d%d",&n,&x,&y) == 3)
    {
        memset(tree,0,sizeof(tree));
        memset(b,0,sizeof(b));
        memset(p,0,sizeof(p));
        for(int i = 1 ; i <= n ; i ++)
        {
            scanf("%d",&p[i].k);
            p[i].i = i;
        }
        sort(p+1,p+n+1);
        int cnt = 1;
        for(int i = 1 ; i <= n ; i ++) ///离散化
        {
            if(i != 1 && p[i].k != p[i-1].k) cnt ++;
            b[p[i].i] = cnt;
        }
        long long sum = 0;
        for(int i = 1 ; i <= n; i ++)
        {
            add(b[i],1);
            sum += i-query(b[i]);
        }
        printf("%lld\n",min(x*sum,y*sum));
    }
    return 0;
}

菜得不一样,菜出新高度。

猜你喜欢

转载自blog.csdn.net/wdaoyuanjun/article/details/81213440
今日推荐