【BZOJ2212】Tree Rotations(POI2011)-平衡树启发式合并
2018-03-11 21:13
429 查看
测试地址:Tree Rotations
做法:本题需要用到平衡树启发式合并。
对于叶子节点,最优答案显然是00。然后对于每棵子树,我们发现由转换它的左右子树所多出的逆序对数,仅和两边都有什么数字有关,而不和两边的数字顺序有关,所以我们对于每个叶子节点存储一棵平衡树,然后在每个节点合并左右子树的平衡树,在合并的同时,算出新增的逆序对数,然后判断要不要转换子树,选择最小的答案累加即可。
以下是本人代码:
做法:本题需要用到平衡树启发式合并。
对于叶子节点,最优答案显然是00。然后对于每棵子树,我们发现由转换它的左右子树所多出的逆序对数,仅和两边都有什么数字有关,而不和两边的数字顺序有关,所以我们对于每个叶子节点存储一棵平衡树,然后在每个节点合并左右子树的平衡树,在合并的同时,算出新增的逆序对数,然后判断要不要转换子树,选择最小的答案累加即可。
以下是本人代码:
#include <bits/stdc++.h> typedef long long ll; using namespace std; int n,tot=0; int top[200010],fa[200010],ch[200010][2],key[200010]; ll ans=0,siz[200010]; void pushup(int x) { siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } void rotate(int x,bool f) { int y=fa[x]; ch[y][!f]=ch[x][f]; fa[ch[x][f]]=y; if (fa[y]) ch[fa[y]][ch[fa[y]][1]==y]=x; fa[x]=fa[y]; fa[y]=x; ch[x][f]=y; pushup(y),pushup(x); } void Splay(int x,int &rt,int goal) { while(fa[x]!=goal) { if (fa[fa[x]]==goal) rotate(x,ch[fa[x]][0]==x); else { int y=fa[x],z=fa[fa[x]]; bool f=(ch[y][1]==x); if (ch[z][f]==y) rotate(y,!f),rotate(x,!f); else rotate(x,!f),rotate(x,f); } } if (!goal) rt=x; } void insert(int &v,int &rt,int x,int f,ll &newans) { if (!v) { v=x; ch[v][0]=ch[v][1]=0; fa[v]=f; siz[v]=1; Splay(v,rt,0); return; } if (key[x]>key[v]) newans+=siz[ch[v][0]]+1; insert(ch[v][key[x]>key[v]],rt,x,v,newans); } int find(int x) { int r=x,i=x,j; while(r!=top[r]) r=top[r]; while(i!=r) j=top[i],top[i]=r,i=j; return r; } ll order(int v,int &rt) { ll newans=0,lson=ch[v][0]; if (ch[v][1]) newans+=order(ch[v][1],rt); insert(rt,rt,v,0,newans); if (lson) newans+=order(lson,rt); return newans; } void merge(int x,int y) { int fx=find(x),fy=find(y),rt; ll sizx,sizy; top[fx]=fy; Splay(x,rt,0),Splay(y,rt,0); if (siz[x]>siz[y]) swap(x,y); sizx=siz[x],sizy=siz[y]; ll newans=order(x,y); ans+=min(newans,sizx*sizy-newans); } void dfs() { int x; scanf("%d",&x); if (x) { int v=++tot; top[v]=v; fa[v]=ch[v][0]=ch[v][1]=0; siz[v]=1; key[v]=x; } else { int ch1,ch2; dfs(); ch1=tot; dfs(); ch2=tot; merge(ch1,ch2); } } int main() { scanf("%d",&n); siz[0]=0; dfs(); printf("%lld",ans); return 0; }
相关文章推荐
- BZOJ 2212([Poi2011]Tree Rotations-启发式合并)
- bzoj 2212 [Poi2011]Tree Rotations(线段树合并)
- [BZOJ2212][Poi2011]Tree Rotations(线段树合并)
- BZOJ 2212 [Poi2011]Tree Rotations(线段树合并)
- BZOJ 2212: [Poi2011]Tree Rotations 线段树合并
- Bzoj2212:[Poi2011]Tree Rotations:线段树的合并
- BZOJ2212 [Poi2011]Tree Rotations 【线段树合并】
- 【BZOJ2212】[Poi2011]Tree Rotations 线段树合并
- BZOJ.2212.[POI2011]Tree Rotations(线段树合并)
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
- bzoj 2212: [Poi2011]Tree Rotations 线段树合并
- BZOJ 2212 [Poi2011]Tree Rotations 线段树合并
- [BZOJ2212][POI2011]Tree Rotations(线段树合并)
- BZOJ_2212_[Poi2011]Tree Rotations_线段树合并
- 【BZOJ】【P2212&P3702】【Poi2011】【Tree Rotations】【二叉树】【题解】【启发式合并】
- BZOJ 2212 & POI 18 Tree Rotations(线段树合并)
- 【bzoj2212】 [Poi2011]Tree Rotations
- [BZOJ2212][Poi2011]Tree Rotations
- bzoj 2212: [Poi2011]Tree Rotations
- BZOJ 2212: [Poi2011]Tree Rotations( 线段树 )