第一道树状数组
用到了贪心的想法
交换的代价就是交换完之后的逆序对数
将所有IOI草从高到低放入
贪心判断是放在左边还是放在右边
会爆int
也要考虑有两棵IOI草高度相同
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=300005;
inline int read(){
int x=0,f=1,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,data[MAXN];
inline void add(int x,int i){
while(x<=n) data[x]+=i,x+=x&(-x);
}
inline int query(int x){
int res=0;
while(x) res+=data[x],x-=x&(-x);
return res;
}
int id[MAXN],a[MAXN];
inline int cmp(int x,int y){
return a[x]>a[y];
}
inline int cal(int x,int num){
int res=query(x);
if(res*2>=num) res=num-res;
// cout<<res<<endl;
return res;
}
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) id[i]=i;
sort(id+1,id+1+n,cmp);
long long ans=0;
for(int i=1;i<=n;i++){
int k=i;
while(k<n&&a[id[k]]==a[id[k+1]]) ans+=cal(id[k],i-1),k++;
ans+=cal(id[k],i-1);
// cout<<k<<endl;
// cout<<ans<<endl;
for(int j=i;j<=k;j++) add(id[j],1);
i=k;
}
printf("%lld\n",ans);
return 0;
}