标签:
神奇的解法感觉很靠谱,但是不会证明
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 400010 #define N 4000100 using namespace std; int lch[N],rch[N],sum[N]; int root[maxn],l[maxn],r[maxn],w[maxn]; int n,m,num,tot; long long ans,cnt1,cnt2; void dfs(int x) { scanf("%d",&w[x]); if (!w[x]) { l[x]=++num; dfs(num); r[x]=++num; dfs(num); } } void update(int x) { sum[x]=sum[lch[x]]+sum[rch[x]]; } void modify(int &x,int l,int r,int d) { if (!x) x=++tot; if (l==r) {sum[x]=1;return;} int mid=(l+r)/2; if (d<=mid) modify(lch[x],l,mid,d); else modify(rch[x],mid+1,r,d); update(x); } int merge(int x,int y) { if (!x) return y; if (!y) return x; cnt1+=(long long)sum[rch[y]]*sum[lch[x]]; cnt2+=(long long)sum[rch[x]]*sum[lch[y]]; lch[x]=merge(lch[x],lch[y]); rch[x]=merge(rch[x],rch[y]); update(x); return x; } void dfs1(int x) { if (!w[x]) { dfs1(l[x]); dfs1(r[x]); cnt1=cnt2=0; root[x]=merge(root[l[x]],root[r[x]]); ans+=min(cnt1,cnt2); } } int main() { scanf("%d",&n); num++;dfs(1); for (int i=1;i<=num;i++) if (w[i]) modify(root[i],1,n,w[i]); dfs1(1); printf("%lld\n",ans); return 0; }
标签:
原文地址:http://blog.csdn.net/u012288458/article/details/51372121