[bzoj3702]二叉树
来源:互联网 发布:淘宝卖蜂蜜需要什么 编辑:程序博客网 时间:2024/06/05 19:08
题目大意
有一个n个叶子结点的树,叶子结点上有权值,且为[1,n]的排列。
你可以交换任一非叶子结点的左右儿子,请最小化中序遍历后的逆序对个数。
线段树合并
显然在一个非叶子结点需要确定左右次序,并且这与其左右子树内的次序无关。
对于每个结点维护一个线段树,那么每次就是合并左右儿子的线段树。
至于如何统计每种次序的逆序对个数,线段树合并的时候统计就好了,具体见代码。
#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;const int maxn=200000+10,maxd=200000*20+10;int root[maxn*2],sum[maxd],left[maxd],right[maxd],tree[maxn*2][2];int i,j,k,l,t,n,m,tot,top;ll ans,cnt1,cnt2;void insert(int &x,int l,int r,int a){ if (!x) x=++tot; if (l==r){ sum[x]++; return; } int mid=(l+r)/2; if (a<=mid) insert(left[x],l,mid,a);else insert(right[x],mid+1,r,a); sum[x]=sum[left[x]]+sum[right[x]];}int merge(int x,int y,int l,int r){ if (!x||!y) return x+y; if (l==r){ sum[x]+=sum[y]; return x; } int mid=(l+r)/2; cnt1+=(ll)sum[left[x]]*sum[right[y]]; cnt2+=(ll)sum[right[x]]*sum[left[y]]; left[x]=merge(left[x],left[y],l,mid); right[x]=merge(right[x],right[y],mid+1,r); sum[x]=sum[left[x]]+sum[right[x]]; return x;}void dfs(int x){ scanf("%d",&t); if (t) insert(root[x],1,n,t); else{ tree[x][0]=++top; dfs(tree[x][0]); tree[x][1]=++top; dfs(tree[x][1]); cnt1=cnt2=0; root[x]=merge(root[tree[x][0]],root[tree[x][1]],1,n); ans+=min(cnt1,cnt2); }}int main(){ scanf("%d",&n); dfs(top=1); printf("%lld\n",ans);}
0 0
- [bzoj3702]二叉树
- bzoj3702 二叉树
- [bzoj3702]二叉树
- 【bzoj3702】二叉树
- 【bzoj3702】【二叉树】【线段树】
- 【bzoj3702】二叉树 权值线段树
- bzoj3702二叉树 线段树合并
- BZOJ3702/2212 [Poi2011]Tree Rotations/二叉树
- [BZOJ3702][BZOJ2212]-线段树合并
- 二叉树、二叉堆
- 二叉树
- 二叉树
- 二叉树
- 二叉树
- 二叉树
- 二叉树
- 二叉树
- 二叉树
- Solr之fieldtype
- java布局总结
- Android Studio常用快捷键
- 计算地铁族的来月出行计划对应的月票预支付最小花费
- Android面试——Java相关
- [bzoj3702]二叉树
- 在windows上通过浏览器远程连接Linux服务器的jupyter
- HDU2521 反素数
- Android面试——编程算法题
- CGroup 介绍、应用实例及原理描述
- [C++]最小生成树--Prim算法&Kruskal算法
- Codeforces 165E Compatible Numbers
- 利用labview动态生成树
- Max Time-Delay Neural Networks