bzoj2212

时间:2023-03-09 18:06:29
bzoj2212

题解:

线段树合并

比较一下哪一种方案的逆序对少

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=;
typedef long long ll;
ll ans,ANS,a[N],cnt,ch[N][],rt[N],cn,CH[N][],sum[N],CNT,n;
void addnew(ll &x,ll l,ll r,ll v)
{
CNT++;x=CNT;
sum[x]++;
if (l==r) return;
ll mid=(l+r)/;
if (v<=mid) addnew(ch[x][],l,mid,v);
else addnew(ch[x][],mid+,r,v);
}
void build(ll &x)
{
cnt++;x=cnt;
scanf("%lld",&a[x]);
if (a[x])
{
addnew(rt[x],,n,a[x]);
return;
}
build(CH[x][]);
build(CH[x][]);
}
ll merge(ll x,ll y)
{
if (!x) return y;
if (!y) return x;
ans+=sum[ch[x][]]*sum[ch[y][]];
ch[x][]=merge(ch[x][],ch[y][]);
ch[x][]=merge(ch[x][],ch[y][]);
sum[x]=sum[ch[x][]]+sum[ch[x][]];
return x;
}
void dfs(ll x)
{
ll lc=CH[x][],rc=CH[x][];
if (a[x]) return;
dfs(lc);dfs(rc);
ll tot=sum[rt[lc]]*sum[rt[rc]];
ans=;
rt[x]=merge(rt[lc],rt[rc]);
ANS+=min(ans,tot-ans);
}
int main()
{
scanf("%lld",&n);
ll root;
build(root);
dfs(root);
printf("%lld",ANS);
}