bzoj 4573: [Zjoi2016]大森林 lct splay
http://www.lydsy.com/JudgeOnline/problem.php?id=4573
http://blog.csdn.net/lych_cys/article/details/53515748#
lct的难点大概是转换的部分。
这道题需建两种权值不同的点,每次更换生长节点建立权值为0的虚点,生长新点建立权值为1的实点,因为最开始有一个带权值的生长节点,那么建一个虚点一个实点来表示。
因为求的东西追根溯源只是链,每棵树从根到某点的链的结构都是交错的所以可以这样压缩点以及点点之间的关系。
实点需要连向最近建立的虚点,虚点需要连向最近建立的实点,注意一下离线前虚点被连成一条链,离线操作时某一个控制范围结束也是将这个虚点连回原来的链上。
按照操作的树的起始位置和操作时间排序,就可以离线处理了。这个离线操作大概可以视为几个实点虚点交错的链两端断开连接。
计算距离lca实现,两次access+splay计算的两个点x和y到根的距离和,他们的lca其实是 access y 的时候的最后一个连通块的入点,这个应该想一下可以想到。
access lca的时候我才发现access是删掉整个右子树的,这样操作顺利删掉了y到lca的这段距离。(原来以前都没有意识到access的原理么我果然是个傻子)。
注释什么的代码里解释的很详细了。
过了157个人,时间空间排名83竟然有点开心(还有74个人想的板子没有我抄的板子快呀(有毒))。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=;
int n,m;
int ch[maxn][]={},fa[maxn]={},siz[maxn]={};//splay相关
int sum[maxn]={},num[maxn]={};//splay子树和,点值(0/1)
int l[maxn]={},r[maxn]={};//对实点的记录,每个实点存在的树的标号范围
int b[maxn]={};//编号为i的实点的编号为b[i]
int tly=,cnt=;//tly是对点数的记录,cnt表示当前生成到编号为cnt的实点
int ans[maxn]={};
struct nod{
int z,ti,x,y;//操作的树的序号 操作时间(排序的一个依据) 需要连的两个点
}a[maxn*];int tot=;
bool mcmp(nod aa,nod bb){ return aa.z<bb.z||(aa.z==bb.z&&aa.ti<bb.ti); }
//离线操作是先按位置后按地点的方式排列的。
inline bool isroot(int x){ return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
inline void updata(int x){ sum[x]=sum[ch[x][]]+sum[ch[x][]]+num[x];}
inline void newp(int v){ tly++;num[tly]=sum[tly]=v; }
inline void init(int z,int ti,int x,int y){
a[++tot].z=z;a[tot].ti=ti;a[tot].x=x;a[tot].y=y;
}
void rotate(int x){
int y=fa[x];int fy=fa[y];
int l=ch[y][]==x?:;int r=l^;
if(!isroot(y)){
if(ch[fy][]==y) ch[fy][]=x;
else ch[fy][]=x;
}
fa[ch[x][r]]=y; fa[x]=fy; fa[y]=x;
ch[y][l]=ch[x][r]; ch[x][r]=y;
updata(y);
}
void splay(int x){
while(!isroot(x)){
int y=fa[x];int fy=fa[y];
if(!isroot(y)){
if((ch[y][]==x)^(ch[fy][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}updata(x);
}
int access(int x){
int y=;
while(x){
splay(x);
ch[x][]=y;
updata(x);
y=x;x=fa[x];//这里的y和上面的含义不同,这里的是儿子。
}return y;
}
void cut(int x){
access(x);splay(x);
fa[ch[x][]]=;ch[x][]=;updata(x);
}
void link(int x,int y){ cut(x);fa[x]=y;}
int main(){
scanf("%d%d",&n,&m);
newp();cnt=;b[]=l[]=;r[]=n;
newp();fa[]=;
int x,y,z,f;int now=;
for(int i=;i<=m;i++){
scanf("%d",&f);
if(!f){
cnt++;
scanf("%d%d",&l[cnt],&r[cnt]);
newp();b[cnt]=tly;
init(,i-m,tly,now);//操作的树的序号 时间(排序的两个依据) 需要连的两个点
}
else if(f==){
scanf("%d%d%d",&x,&y,&z);
x=max(x,l[z]);y=min(y,r[z]);
if(x<=y){
newp();
if(x>)fa[tly]=now;
init(x,i-m,tly,b[z]);
init(y+,i-m,tly,now);
now=tly;
}
}
else{
scanf("%d%d%d",&z,&x,&y);
init(z,i,b[x],b[y]);
}
}
sort(a+,a++tot,mcmp);
memset(ans,-,sizeof(ans));
int j=;
for(int i=;i<=n;i++){
for(;j<=tot&&a[j].z==i;j++){
if(a[j].ti>){
access(a[j].x);splay(a[j].x);
ans[a[j].ti]=sum[a[j].x];
x=access(a[j].y);
splay(a[j].y);
ans[a[j].ti]+=sum[a[j].y];
access(x);splay(x);
ans[a[j].ti]-=sum[x]*; }
else{
link(a[j].x,a[j].y);
}
}
}for(int i=;i<=m;i++)if(ans[i]!=-)printf("%d\n",ans[i]);
return ;
}
bzoj 4573: [Zjoi2016]大森林 lct splay的更多相关文章
- 【刷题】BZOJ 4573 [Zjoi2016]大森林
Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力.小 ...
- bzoj 4573: [Zjoi2016]大森林
Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树 都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. ...
- [ZJOI2016]大森林(LCT)
题目描述 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. 小Y掌握了一种 ...
- 洛谷P3348 [ZJOI2016]大森林 [LCT]
传送门 刷了那么久水题之后终于有一题可以来写写博客了. 但是这题太神仙了我还没完全弄懂-- upd:写完博客之后似乎懂了. 思路 首先很容易想到\(O(n^2\log n)\)乘上\(O(\frac{ ...
- BZOJ4573:[ZJOI2016]大森林——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=4573 https://www.luogu.org/problemnew/show/P3348#sub ...
- [ZJOI2016]大森林
Description: 小Y家里有一个大森林,里面有n棵树,编号从1到n 0 l r 表示将第 l 棵树到第 r 棵树的生长节点下面长出一个子节点,子节点的标号为上一个 0 号操作叶子标号加 1(例 ...
- P3348 [ZJOI2016]大森林
\(\color{#0066ff}{ 题目描述 }\) 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点, ...
- 【LuoguP3348】[ZJOI2016]大森林
题目链接 题目描述 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. 小Y ...
- UOJ#195. 【ZJOI2016】大♂森林 LCT
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ195.html 题解 首先询问都可以放到最后处理. 对于操作,我们把它差分一下离线下来. 现在的问题就是从 ...
随机推荐
- js数据类型隐式转换问题
js数据类型隐式转换 ![] == false //true 空数组和基本类型转换,会先[].toString() 再继续比较 ![] == [] //true ![] //false [] == [ ...
- Win7下VS2010不能链接问题
装了2012准备学VC++窗体开发,然后发现手边只有VS2010的教程,于是卸掉VS2012改装VS2010,结果发现不管写啥,链接时都报错“error Link1123 转到coff期间失败”. 于 ...
- zookeeper zkClient api 使用
操作步骤: 一.引入zkclient的jar包(maven方式) <dependency> <groupId>com.101tec</groupId> <ar ...
- AndroidManifest.xml权限设置
访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permi ...
- MySQL 5.7.17 Group Relication(组复制)搭建手册【转】
本博文介绍了Group Replication的两种工作模式的架构.并详细介绍了Single-Master Mode的部署过程,以及如何切换到Multi-Master Mode.当然,文末给出了Gro ...
- order by 的列名不能参数化,要拼sql
from T_COMPANY c join T_COMPANY_POSITION p on c.ID = p.COMPANYID order by :type desc nulls last; 最初不 ...
- STL容器 vector,list,deque 性能比较
C++的STL模板库中提供了3种容器类:vector,list,deque对于这三种容器,在觉得好用的同时,经常会让我们困惑应该选择哪一种来实现我们的逻辑.在少量数据操作的程序中随便哪一种用起来感觉差 ...
- 十五、springboot集成定时任务(Scheduling Tasks)(二)之(线程配置)
配置类: /** * 定时任务线程配置 * */ @Configuration public class SchedulerConfig implements SchedulingConfigurer ...
- SQL中rownum和order by的执行顺序的问题
在一个SQL中,如果同时使用rownum和order by,会有一个先后顺序的问题. 比如select id1,id2 from t_tablename where rownum<3 order ...
- Spark(十五)SparkCore的源码解读
一.启动脚本分析 独立部署模式下,主要由master和slaves组成,master可以利用zk实现高可用性,其driver,work,app等信息可以持久化到zk上:slaves由一台至多台主机构成 ...