比赛时摸了半天,不知道什么时候取得最小值,后来发现如果y<x,则不断通过交换相邻的两个逆序数,就能取得最小值,而总的交换次数刚好为逆序数对的个数。。所以直接求逆序数对数判断x,y就好了
线段树
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int A[100100],B[100100],T[1000100],ha[100100];
int update(int root,int l,int r,int x){
if(l==r){
T[root]++;
return 0;
}
int ans=0,mid=(l+r)/2;
if(x<=mid) ans+=update(root*2,l,mid,x);
else ans+=T[root*2]+update(root*2+1,mid+1,r,x);
T[root]=T[root*2]+T[root*2+1];
return ans;
}
int main(){
int i,n,x,y;
while(scanf("%d%d%d",&n,&x,&y)!=EOF){
memset(T,0,sizeof(T));
for(i=1;i<=n;i++){
scanf("%d",&A[i]);
B[i]=A[i];
}
sort(B+1,B+1+n);
int k=0;
ha[k++]=B[1];
for(i=2;i<=n;i++){
if(B[i]!=B[i-1]) ha[k++]=B[i];
}
long long sum=0;
for(i=n;i>=1;i--){
int a=lower_bound(ha,ha+k,A[i])-ha;
sum+=update(1,0,100005,a);
}
if(x>y) printf("%lld\n",sum*y);
else printf("%lld\n",sum*x);
}
return 0;
}
树状数组
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<set>
using namespace std;
int A[100010],cnt[100010],B[100010],ha[100010];
set<int>s;
int lowbit(int x){
return -x&x;
}
void update(int x,int k){
while(x<=100010){
A[x]+=k;
x+=lowbit(x);
}
}
int q(int x){
int sum=0;
while(x){
sum+=A[x];
x-=lowbit(x);
}
return sum;
}
int main(){
int x,y,n,i,a;
while(scanf("%d%d%d",&n,&x,&y)!=EOF){
memset(A,0,sizeof(A));
memset(cnt,0,sizeof(cnt));
s.clear();
long long sum=0;
for(i=1;i<=n;i++){
scanf("%d",&B[i]);
s.insert(B[i]);
}
set<int>::iterator it;
int k=1;
for(it=s.begin();it!=s.end();it++) ha[k++]=*it;
for(i=n;i>=1;i--){
a=lower_bound(ha+1,ha+k,B[i])-ha;
sum+=q(a);
sum-=cnt[a];
cnt[a]++;
update(a,1);
}
if(x>y) cout<<sum*y<<endl;
else cout<<sum*x<<endl;
}
return 0;
}