BZOJ.2212.[POI2011]Tree Rotations(线段树合并)
题目链接
\(Description\)
给定一棵n个叶子的二叉树,每个叶节点有权值(1<=ai<=n)。可以任意的交换两棵子树。问最后顺序遍历树得到的叶子权值序列中,最少的逆序对数是多少。
\(Solution\)
很重要的一点是在子树内部交换左右儿子对其它子树是没有影响的。(当然更大区间内交换两棵子树对子树内部也是没有影响的)
所以DFS,对每个节点的两棵子树,如果换了更优就换,不优就不换。
怎么统计两棵子树换/不换产生的逆序对数呢,用两棵子树的值域线段树合并解决。换/不换产生的逆序对数根据子树的大小关系判断就行了。
时间空间都是\(O(n\log n)\).
在这里记一下我个人对线段树合并复杂度的感性证明吧...(好像就是势能分析)
每次合并两棵树,代价是两棵树的公共节点数,设它是\(x\)。
在合并完两棵树后,这两棵树的\(2*x\)个公共节点被合并成了\(x\)个,相当于删掉了\(x\)个点。
所以合并的代价(复杂度)就是,被合并点的点的个数,也就是删掉的点的个数。
而要删掉这个点就要先存在这个点,初始一共有\(n\log n\)个节点,所以删掉点的个数不会超过\(n\log n\),所以总复杂度不会超过\(n\log n\)。如果初始是对每个节点进行一次区间修改,和插入单点一样只会影响\(\log n\)个点,所以初始还是一共最多有\(n\log n\)个点,复杂度一样。
另外复杂度也不完全是公共节点数,因为还要从它往下一层才知道它是公共节点。
也许是因为这个能卡一些线段树合并的复杂度吧,但是影响不大不管了。
//80628kb 7088ms
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=2e5+5;int n;
LL Ans;
char IN[MAXIN],*SS=IN,*TT=IN;
struct Segment_Tree
{#define S N*19//只有建树、合并的话 nlogn就够了 n(logn+1)!#define lson son[x][0]#define rson son[x][1]int tot,sz[S],son[S][2];void Insert(int &x,int l,int r,int p){sz[x=++tot]=1;if(l==r) return;int m=l+r>>1;if(p<=m) Insert(lson,l,m,p);else Insert(rson,m+1,r,p);}int Merge(int x,int y,LL &ans1,LL &ans2){if(!x||!y) return x^y;ans1+=1ll*sz[rson]*sz[son[y][0]], ans2+=1ll*sz[lson]*sz[son[y][1]];lson=Merge(lson,son[y][0],ans1,ans2);rson=Merge(rson,son[y][1],ans1,ans2);sz[x]+=sz[y];// sz[x]=sz[lson]+sz[rson]; 这种写法在合并叶子节点时不对啊!(y更新不了x)return x;}
// void Print(int x,int l,int r)
// {
// if(!x) return;
// printf("%d:%d~%d sz:%d\n",x,l,r,sz[x]);
// if(l==r) ;
// else Print(lson,l,l+r>>1), Print(rson,(l+r>>1)+1,r);
// }
}T;inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}
int DFS()//返回root
{int v=read();if(v) {int x; T.Insert(x,1,n,v); return x;}LL ans1=0, ans2=0;int rt=T.Merge(DFS(),DFS(),ans1,ans2);//当然参数顺序是反着的 Ans+=std::min(ans1,ans2);return rt;
}int main()
{n=read(), DFS(), printf("%lld\n",Ans);return 0;
}
转载于:https://www.cnblogs.com/SovietPower/p/9300819.html
BZOJ.2212.[POI2011]Tree Rotations(线段树合并)相关推荐
- [Poi2011]Tree Rotations线段树合并
整理一下线段树合并的思路,大体是给每个树上节点分配一个根编号建一棵log长的权值线段树,一开始树上只有这个树节点的节点权 merge两个树节点的时候,对于当前合并的值域(例如两棵线段树的表示1到n/2 ...
- BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)
题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...
- BZOJ 3910 并查集+线段树合并
思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...
- BZOJ 4399: 魔法少女LJJ 线段树合并 + 对数
Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了 LJJ感叹道"这里真是个迷人的绿色世界,空气清新.淡雅 ...
- 【BZOJ2212】【POI2011】Tree Rotations(线段树合并)
Description click me Solution 对于每个节点有一棵权值线段树,向上递归时合并同时计算逆序对即可. Source /***************************** ...
- 数据结构之线段树合并——永无乡,Lomsat gelral,Tree Rotations,Tree Rotations Escape Through Leaf
文章目录 [HNOI2012]永无乡 Lomsat gelral 「POI2011 R2 Day2」旋转树木 Tree Rotations Escape Through Leaf 线段树合并与 fhq ...
- UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)
NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...
- BZOJ 3277 串 BZOJ 3473 字符串 (广义后缀自动机、时间复杂度分析、启发式合并、线段树合并、主席树)...
标签那么长是因为做法太多了... 题目链接: (bzoj 3277) https://www.lydsy.com/JudgeOnline/problem.php?id=3277 (bzoj 3473) ...
- 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree...
原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...
最新文章
- 安徽自考计算机基础考试时间,安徽2021年4月自考考试时间
- php 清除之前echo_PHP入门读书笔记(三): 常量和变量
- Linux疑难杂症解决方案100篇(二十)-Linux正则表达式(实用)指南
- crossin的编程教室python入门_简单三步,用 Python 发邮件
- Notepad++使用技巧
- Javascript实现获取及设置光标位置的方法
- Unity3D基础4:空物体与预制体
- linux安装cd dev ls,linux 第一节 安装
- 离线安装docker镜像
- Tomcat - SSL操作大全
- 打印的时候显示域服务器不可用,Win10打印时active directory域服务不可用解决方法...
- node.js实现微信授权登陆
- 高效人士睡觉前做的10件事
- c语言找出成绩的最大,C语言 求每个学生、每门课的平均成绩并找出最大值
- iOS逆向一:数字签名苹果应用双重签名原理应用重签名
- 11.03 CSS的基础应用
- 宝藏动植物元素矢量图素材,速来收藏
- JPA 查询 未查询到时返回的list的size为0 但是引用并不为空
- 论文代码Chrome神器:去谷歌学术搜到文章,代码链接就能自动展示
- php 合并对象_PHP合并数组对象
热门文章
- Python 技巧篇-让我的程序暂停一下
- 【linux操作回炉1】
- sepFilter2D函数
- selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary
- 【解决方案】vue不是内部或外部命令
- 感知机模型[神经网络入门]
- 11.1自定义异常类
- android网页无法定位吗,在android中,js 无法定位 html页面的某元素
- linux系统管理常用命令
- 什么是Java内存模型中的happens-before