bzoj3702二叉树 线段树合并
2017-06-03 21:48
288 查看
二倍经验:2212.
很久以前就打了这题,现在回来填坑。。
这题的话是标准的线段树合并。
线段树合并的话,对于一些(大部分)情况,比启发式合并要好很多,时间复杂度少一个log,实现也简单。。
这题来说的话,就是直接合并两个子树,子树中的答案=左子树中的逆序对+右子树中的逆序对+跨越左右的逆序对,前两个扫一遍就可以统计了,问题是最后那个跨越左右子树的逆序对。
假设我们现在合并两颗子树,一颗的根为x,另一颗为y。
由于在合并前,我们已经统计出了x,y的最小逆序对数,我们现在就要统计跨越他们之间的逆序对数量。
然后。。这里我们要对整棵树建权值线段树,保证我们合并的时候的逆序对可以直接计算。
统计逆序对的时候直接枚举是否交换就好了。
很久以前就打了这题,现在回来填坑。。
这题的话是标准的线段树合并。
线段树合并的话,对于一些(大部分)情况,比启发式合并要好很多,时间复杂度少一个log,实现也简单。。
这题来说的话,就是直接合并两个子树,子树中的答案=左子树中的逆序对+右子树中的逆序对+跨越左右的逆序对,前两个扫一遍就可以统计了,问题是最后那个跨越左右子树的逆序对。
假设我们现在合并两颗子树,一颗的根为x,另一颗为y。
由于在合并前,我们已经统计出了x,y的最小逆序对数,我们现在就要统计跨越他们之间的逆序对数量。
然后。。这里我们要对整棵树建权值线段树,保证我们合并的时候的逆序对可以直接计算。
统计逆序对的时候直接枚举是否交换就好了。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 400010 #define N 4000100 using namespace std; int lch ,rch ,sum ; 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; }
相关文章推荐
- bzoj 3702: 二叉树 线段树合并
- bzoj3702二叉树 线段树合并
- 【bzoj3702】【二叉树】【线段树】
- [BZOJ3702][BZOJ2212]-线段树合并
- bzoj 3702: 二叉树 (线段树)
- 【bzoj3702】二叉树 权值线段树
- bzoj2212&3702 [Poi2011]Tree Rotations 二叉树 (线段树合并)
- BZOJ 2733 [HNOI2012]永无乡 可持久化线段树合并
- BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)
- 【bzoj1593】[Usaco2008 Feb]Hotel 旅馆 线段树区间合并
- bzoj4530[Bjoi2014]大融合 线段树合并+dfs序+并查集
- BZOJ 4756 Promotion Counting(线段树合并 || dfs)
- bzoj 3307: 雨天的尾巴【树剖lca+树上差分+线段树合并】
- [BZOJ]3439: Kpm的MC密码 trie树+主席树(线段树合并)
- BZOJ 3307: 雨天的尾巴( LCA + 线段树合并 )
- BZOJ[2733][HNOI2012]永无乡 线段树合并+并查集
- 【线段树区间合并】BZOJ1593-[Usaco2008 Feb]Hotel 旅馆
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting 线段树合并
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
- BZOJ.2212.[POI2011]Tree Rotations(线段树合并)