线段树合并
BZOJ2212
#include <cstdio> #include <iostream> #define LL long long using namespace std; int cnt,n; LL tmp,tot,ans; struct treenode{ LL size,lc,rc; }tr[4000001]; int newnode(int l,int r,int tar){ tr[++cnt].size=1; if (l==r) return(cnt); int mid=(l+r)>>1,t=cnt; if (tar<=mid) tr[t].lc=newnode(l,mid,tar);else tr[t].rc=newnode(mid+1,r,tar); return(t); } int merge(int poa,int pob,int l,int r){ if (poa==0) return(pob); if (pob==0) return(poa); tr[poa].size+=tr[pob].size; if (l==r) return(poa); tmp+=tr[tr[poa].lc].size*tr[tr[pob].rc].size; int mid=(l+r)>>1,t=poa; tr[poa].lc=merge(tr[poa].lc,tr[pob].lc,l,mid); tr[poa].rc=merge(tr[poa].rc,tr[pob].rc,mid+1,r); return(poa); } int work(){ int t; scanf("%d",&t); if (t!=0){return(newnode(1,n,t));}else{ int t1=work(),t2=work(); tot=tr[t1].size*tr[t2].size,tmp=0; int ret=merge(t1,t2,1,n); ans+=min(tmp,tot-tmp); return(ret); } } int main(){ scanf("%d",&n); work(); printf("%lld\n",ans); }