链接: http://acm.hdu.edu.cn/showproblem.php?pid=6318
来源: 2018 Multi-University Training Contest 2
思路:求出逆序对ans后,答案就是ans*min(x,y),模板即可
#include<bits/stdc++.h>
#define LNode x<<1
#define RNode x<<1|1
using namespace std;
typedef long long ll;
const int Max_n=1e5+10;
int sum[4*Max_n],a[Max_n],bin[Max_n];
void build(int l,int r,int x){//构建线段树(自顶向下)
if(l==r){ sum[x]=0; return ; }
int mid=l+(r-l)/2;
build(l,mid,LNode);
build(mid+1,r,RNode);
sum[x]=sum[LNode]+sum[RNode];
//build(1,n,1);//从根开始向上建立线段树
}
//线段树查询(自顶向下)
int query(int A,int B,int l,int r,int x){///区间查询和(log(n)))
if(A<=l&&B>=r) return sum[x];
int mid=l+(r-l)/2,ans=0;
if(A<=mid) ans+=query(A,B,l,mid,LNode);//查询左子树
if(B>mid) ans+=query(A,B,mid+1,r,RNode);//查询右子树
return ans;
}
//pos位置改为v,[l,r]:当前结点对应的区间,x:当前结点
void change(int pos,int l,int r,int x){///单点修改数据(log(n))
if(l==r) {sum[x]+=1; return ;}
int mid=l+(r-l)/2;
if(pos<=mid) change(pos,l,mid,LNode);
else change(pos,mid+1,r,RNode);
sum[x]=sum[LNode]+sum[RNode];
}
int main(){
int n,x,y;
while(~scanf("%d%d%d",&n,&x,&y)){
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
//离散化
int cnt=0;
for(int i=1;i<=n;i++)
bin[++cnt]=a[i];
sort(bin+1,bin+n+1);
cnt=unique(bin+1,bin+n+1)-bin-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(bin+1,bin+cnt+1,a[i])-bin;
//for(int i=1;i<=n;i++) cout<<a[i]<<" ";
ll ans=0;
build(1,n,1);
for(int i=1;i<=n;i++){
ans+=(ll)query(a[i]+1,n,1,n,1);//查询区间和
//cout<<ans<<endl;
change(a[i],1,n,1);//将sum[i]++
}
//cout<<ans<<endl;
printf("%lld\n",ans*(ll)min(x,y));
}
return 0;
}