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.
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.
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
题意:
输入3,表示有3头牛要排序。2 3 1分别表示三头牛的暴躁水平。为了减少破坏,每相邻的两头牛可以互换使得全部牛按照暴躁程度递增的顺序排列。暴躁水平为交换时间。求最少交换时间。所以样例应该输出7.
2 3 1
第一次交换后顺序 2 1 3 ,花费时间1+3=4;
第二次交换后顺序1 2 3 ,花费时间1+2=3.所以共花去时间7=3+4.
思路解析:
对于当前数X,我们如果知道前面比它大的数有多少,假设为K,那么有部分代价(花费的时间)是确定的,那就是K*X;然后还得加上比它大的那些数之和,这就是当数列到X为止,排好所需要的最小代价。
求比它大的数的个数就是求逆序数,用树状数组完美解决,K1即是逆序对数(一定要__int64),接下来就是求总和,我们可以用get_sum(n)与get_sum(x)的差来表示(题目中数的范围为1-N)。
见代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define N 100005
int n;
struct node
{
int index;
__int64 sum;
}c[N];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int k,int s)
{
while(x<=n)
{
c[x].index+=k;
c[x].sum+=s;
x+=lowbit(x);
}
}
int getsum_index(int x)
{
int ans=0;
while(x>0)
{
ans+=c[x].index;
x-=lowbit(x);
}
return ans;
}
__int64 getsum_sum(int x)
{
__int64 ans=0;
while(x>0)
{
ans+=c[x].sum;
x-=lowbit(x);
}
return ans;
}
int main(void)
{
while(scanf("%d",&n))
{
int i;
__int64 ans=0;
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
update(x,1,x);
__int64 k1=i-getsum_index(x);
if(k1!=0)
{
__int64 k2=getsum_sum(n)-getsum_sum(x);
ans=ans+k1*x+k2;
}
}
printf("%I64d\n",ans);
}
}