传送门
这道题考察了对线段树合并的理解程度,在合并线段树的过程中就可以计算逆序对。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2e5+10;
int n,ls[N*50],rs[N*50],val[N*50],tot,root,rt[N*50];
LL ans,ans1,ans2;
struct SegTrees{
#define mid (l+r>>1)
int sum[N*50],ls[N*50],rs[N*50],tot;
void upd(int &id,int l,int r,int pos){
if(!id) id=++tot;
if(l==r) {sum[id]++;return;}
if(pos<=mid) upd(ls[id],l,mid,pos);
else upd(rs[id],mid+1,r,pos);
sum[id]=sum[ls[id]]+sum[rs[id]];
}
void merge(int &x,int y,int l,int r){
if(!x||!y) {x=x+y;return;}
if(l==r) {sum[x]+=sum[y];return;}
ans1+=1ll*sum[rs[x]]*sum[ls[y]];
ans2+=1ll*sum[rs[y]]*sum[ls[x]];
merge(ls[x],ls[y],l,mid);
merge(rs[x],rs[y],r,mid);
sum[x]=sum[ls[x]]+sum[rs[x]];
}
#undef mid
}trs;
void predfs(int &id){
id=++tot;
scanf("%d",&val[id]);
if(val[id]) return;
predfs(ls[id]);
predfs(rs[id]);
}
void dfs(int &u){
if(val[u]) {trs.upd(rt[u],1,n,val[u]);return;}
dfs(ls[u]);dfs(rs[u]);
ans1=ans2=0;
int rson=rs[u];u=ls[u];
trs.merge(rt[u],rt[rson],1,n);
ans+=min(ans1,ans2);
}
int main(){
scanf("%d",&n);
predfs(root);
dfs(root);
printf("%lld
",ans);
return 0;
}