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 题解 首先询问都可以放到最后处理. 对于操作,我们把它差分一下离线下来. 现在的问题就是从 ...
随机推荐
- HTML5之2D物理引擎 Box2D for javascript Games 系列 第一部分
我要的是能在H5页面上跑的javascript版的Box2D啊!!! 最近想学习Javascript版本的Box2D JS物理引擎,无奈搜了半天也没找到相对比较系统的资料 官方网站也只是简单的介绍,A ...
- ubuntu更新源列表
1. 备份源列表 sudo cp /etc/apt/sources.list /etc/apt/sources.list_backup 2.修改更新源 打开源列表 sudo gedit /etc/ap ...
- HTTP之一 If-Modified-Since & If-None-Match
If-Modified-Since & If-None-MatchIf-Modified-Since,和 Last-Modified 一样都是用于记录页面最后修改时间的 HTTP 头信息,只是 ...
- [How to] Phoenix 与 CDH5.4.2 HBase的整合
1.简介 Phoenix将SQL带回到了NOSQL的世界,其在HBase之上做了一个layer,客户端通过SQL调用Phoenix,Phoenix在转化为HBase客户算API进行访问HBase,其很 ...
- 数据库-mysql管理
MySQL 管理 启动及关闭 MySQL 服务器 首先,我们需要通过以下命令来检查MySQL服务器是否启动: ps -ef | grep mysqld 如果MySql已经启动,以上命令将输出mysql ...
- 树莓派指定静态IP
1.备份并清空 interfaces 文件 cp /etc/network/interfaces /etc/network/interfaces.bak vi /etc/network/interfa ...
- java基础77 Http协议及Servlet中的GET、POST提交方式
本文知识点(目录): 1.什么是http协议 2.查看http协议的工具 3.http协议的内容 4.请求方式 5.请求头和响应头(以及获取请求头信息的方法) 6.实体内 ...
- java基础26 线程的通讯;wait()、notify()、notifyAll()等方法
线程的通讯:一个线程完成了自己的任务时,要通知另一个线程去完成另一个任务 1.1.方法 wait():等待.如果线程执行到了wait()方法,那么该线程会进入等待状态,等待状态下的线程必须要被其他线程 ...
- No.13 selenium for python 单选框和复选框
单选框 radio 点击图标,可以获取HTML中定位. 使用普通的ID定位就可以了 定位到指定元素,然后使用clicd选中即可 复选框 checkbox 勾选单个框,跟单选框一样,定位后点击就可以了 ...
- Javascript之浏览器兼容EventUtil
var EventUtil = { //添加事件处理程序 addHandler: function (element, type, handler) { if (element.addEventLis ...