题目链接:点击打开链接
题意描述:给定一个长度为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