[bzoj3702] 二叉树
Posted czllgzmzl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj3702] 二叉树相关的知识,希望对你有一定的参考价值。
一个节点的儿子是否交换,不会影响到它和兄弟节点间的逆序对数。
所以每次合并线段树的时候算一下交换与不交换的逆序对数,然后选个较小值就行了。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define ll long long 7 using namespace std; 8 const int maxn=400233,mxnode=200233*20; 9 int lc[mxnode],rc[mxnode],sz[mxnode],tot; 10 int ls[maxn],rs[maxn],size[maxn],mp[maxn],tt,rt[maxn]; 11 int i,j,k,n,m,presz,P,id,root; 12 ll num0,num1,ans; 13 14 int ra;char rx; 15 inline int read(){ 16 rx=getchar(),ra=0; 17 while(rx<\'0\'||rx>\'9\')rx=getchar(); 18 while(rx>=\'0\'&&rx<=\'9\')ra*=10,ra+=rx-48,rx=getchar();return ra; 19 } 20 21 int merge(int a,int b){ 22 if(!b){presz+=sz[a];return a;} 23 if(!a){num0+=1LL*sz[b]*presz;return b;} 24 sz[a]+=sz[b]; 25 rc[a]=merge(rc[a],rc[b]),lc[a]=merge(lc[a],lc[b]); 26 return a; 27 } 28 void build(int &x,int a,int b){ 29 x=++tot,sz[x]=1; 30 if(a==b)return; 31 int mid=a+b>>1; 32 if(P<=mid)build(lc[x],a,mid);else build(rc[x],mid+1,b); 33 } 34 void in(int &x){ 35 x=++tt,id=read(); 36 if(id)mp[x]=id,size[x]=1;else 37 in(ls[x]),in(rs[x]),size[x]=size[ls[x]]+size[rs[x]]; 38 } 39 void dfs(int x){ 40 if(size[x]==1){P=mp[x],build(rt[x],1,n);return;} 41 dfs(ls[x]),dfs(rs[x]), 42 presz=num0=0,rt[x]=merge(rt[ls[x]],rt[rs[x]]); 43 num1=1LL*size[ls[x]]*size[rs[x]]-num0; 44 // printf(" %d %lld %lld\\n",x,num0,num1); 45 ans+=min(num0,num1); 46 } 47 int main(){ 48 n=read(); 49 in(root);//printf("cnt: %d\\n",cnt); 50 dfs(1); 51 printf("%lld\\n",ans); 52 return 0; 53 }
以上是关于[bzoj3702] 二叉树的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj2212][Poi2011]Tree Rotations
BZOJ_1864_[Zjoi2006]三色二叉树_树形DP