bzoj 4573
LCT神题...
首先暴力的做法就是每次在一个区间上link,然后暴力查询,时间复杂度$O(爆炸)$
但是我们可以发现的是,每棵树之间互不影响!
因此我们可以考虑离线之后分别统计每棵树
但是这样做其实并没有优化时空啊!
但是等等,我们在考虑一下:我们的操作都是区间操作,也就是说我们可以用一个类似差分的思想,一棵树一棵树地处理,处理到区间端点的时候修改一些东西就行了!
那么更换生长节点怎么办?
我们建立一个虚点表示生长节点,然后把新产生的点都连到这个点上就行
于是思路就顺理成章了:
对于新建节点的操作,我们新生成一个点权为1的节点,记录下这个节点生效的区间,然后把他挂到现在的生长节点上
对于更换生长节点的操作,我们新建一个点权为0的节点,将读入的区间与这个点生效的区间取交集作为有效的区间,在这个区间左端点把他挂在要求的实际节点上,右端点挂回虚节点链上
对于查询操作,直接用LCA查询即可,求LCA的方法见代码中access函数
然后离线所有操作,先按树的标号排序(注意新建节点的操作都认为是第一棵树上的,这样后面才能产生足够的节点去移动),先进行修改再进行查询(可以在排序时通过正负把查询排到后面)
这样问题就解决了
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct Ques
{
int pos,typ;
int x,y;
Ques (){}
Ques (int a,int b,int c,int d):pos(a),typ(b),x(c),y(d){}
friend bool operator < (Ques a,Ques b)
{
return a.pos==b.pos?a.typ<b.typ:a.pos<b.pos;
}
}q[400005];
int ch[400005][2];
int siz[400005],f[400005],val[400005];
int ret[400005];
int fl[400005],fr[400005];
int lq[400005],rq[400005];
int n,m,Q;
int tot=0,cnt=0,ttop=0;
void update(int x)
{
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+val[x];
}
bool be_root(int x)
{
if(ch[f[x]][0]==x||ch[f[x]][1]==x)return 0;
return 1;
}
void rotate(int x)
{
int y=f[x],z=f[y],k=(ch[y][1]==x);
if(!be_root(y))ch[z][ch[z][1]==y]=x;
f[x]=z;
ch[y][k]=ch[x][!k],f[ch[x][!k]]=y;
ch[x][!k]=y,f[y]=x;
update(y),update(x);
}
void splay(int x)
{
while(!be_root(x))
{
int y=f[x],z=f[y];
if(!be_root(y))
{
if((ch[z][1]==y)^(ch[y][1]==x))rotate(x);
else rotate(y);
}
rotate(x);
}
//update(x);
}
int access(int x)
{
int y=0;
while(x)
{
splay(x);
ch[x][1]=y;
update(x);
y=x,x=f[x];
}
return y;
}
void link(int x,int y)
{
splay(x),f[x]=y;
}
void cut(int x)
{
access(x),splay(x),f[ch[x][0]]=0,ch[x][0]=0,update(x);
}
void new_node(int x)
{
tot++,val[tot]=siz[tot]=x;
}
int query(int x,int y)
{
int ret=0,fa;
access(x),splay(x),ret+=siz[x];
fa=access(y),splay(y),ret+=siz[y];
access(fa),splay(fa),ret-=2*siz[fa];
return ret;
}
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
n=read(),m=read();
new_node(1),new_node(0);
cnt=1,lq[1]=fr[1]=1,rq[1]=n;
int las=2;link(2,1);
for(int i=1;i<=m;i++)
{
int t=read();
if(!t)
{
int l=read(),r=read();
new_node(1);
lq[++cnt]=l,rq[cnt]=r,fr[cnt]=tot;
q[++ttop]=Ques(1,i-m,tot,las);
}else if(t==1)
{
int l=read(),r=read(),x=read();
l=max(l,lq[x]),r=min(r,rq[x]);
if(l<=r)
{
new_node(0),link(tot,las);
q[++ttop]=Ques(l,i-m,tot,fr[x]);
q[++ttop]=Ques(r+1,i-m,tot,las);
las=tot;
}
}else
{
int x=read(),st=read(),ed=read();
q[++ttop]=Ques(x,++Q,fr[st],fr[ed]);
}
}
sort(q+1,q+ttop+1);
int last=1;
for(int i=1;i<=n;i++)
{
while(q[last].pos==i&&last<=ttop)
{
if(q[last].typ<=0)cut(q[last].x),link(q[last].x,q[last].y);
else ret[q[last].typ]=query(q[last].x,q[last].y);
last++;
}
}
for(int i=1;i<=Q;i++)printf("%d\n",ret[i]);
return 0;
}
bzoj 4573的更多相关文章
- [BZOJ 4573][ZJOI 2016]大森林
[LOJ 2092][BZOJ 4573][UOJ 195][ZJOI 2016]大森林 题意 给定一个树序列, 初始时所有树都只有一个点, 要求支持三种操作: 区间种树(在某个特定点上长出一个子结点 ...
- bzoj 4573 大森林
bzoj 4573 大森林 由于树上路径是唯一的,查询合法的两个点间路径长度显然与其他加点操作无关,所以可以离线处理,将所有的查询放在加点后. 这样我们可以对每棵树都在上颗树的基础上处理好形态后,处理 ...
- bzoj 4573: [Zjoi2016]大森林 lct splay
http://www.lydsy.com/JudgeOnline/problem.php?id=4573 http://blog.csdn.net/lych_cys/article/details/5 ...
- 【刷题】BZOJ 4573 [Zjoi2016]大森林
Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力.小 ...
- bzoj 4573: [Zjoi2016]大森林
Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树 都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. ...
- 【总结】Link-Cut Tree
这是一篇关于LCT的总结 加删边的好朋友--Link Cut Tree Link-Cut Tree,LCT的全称 可以说是从树剖引出的问题 树剖可以解决静态的修改或查询树的链上信息:那如果图会不断改变 ...
- BZOJ 1051 受欢迎的牛(Tarjan缩点)
1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4573 Solved: 2428 [Submit][S ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
随机推荐
- (已解决)MYSQL怎么实现表的id在插入删除的前提下连续递增?
其实就是用了sql语句. 思路是重置所有id和auto_increment. SET @i=0; UPDATE records SET id=(@i:=@i+1); ALTER TABLE recor ...
- docker+react+nginx部署
一.准备工作 1.先确保项目可以正常运行. 2.如果拉代码到Linux下进行打包,注意node版本,我就是版本不同,yarn build一直不成功. 3.找一个nginx的配置文件nginx.conf ...
- docker 实现原理
实现原理 docker虚拟化 的核心是需要解决两个问题,资源隔离与资源限制 虚拟机是通过硬件虚拟化技术,通过一个 hypervisor 层实现对资源的彻底隔离 容器则是通过操作系统级别的虚拟化技术,利 ...
- zip()
a=[1,2,3,4]b=[5,6,7,8]c=[10,11,12,13]zi=zip(a,b,c)print(list(zi)) 结果 [(1, 5, 10), (2, 6, 11), (3, 7, ...
- Raid磁盘阵列更换磁盘时另一块盘离线恢复案例(v7000存储数据恢复)
Raid磁盘阵列更换磁盘时另一块盘离线恢复案例(v7000存储数据恢复) [故障描述]客户设备型号为IBM V7000存储,架构为AIX+oracle+V7000存储阵列柜,需要恢复的数据主要存放在阵 ...
- Cannot add middleware after an application has started
This helped: Open the Command Prompt or the Windows PowerShell. Navigate to your Stable Diffusion fo ...
- RHEL8注册
安装RHEL后,因为是商用系统,YUM软件仓库是不能使用的,需要注册后才可以使用.个人用户可以去红帽官网申请开发者账户. https://developers.redhat.com/ 有了开发者账户后 ...
- C# 子类与父类互转注意项
昨晚在处理父类与子类相互转换时,想把父类转换子类对象,发现编译不通过 ,类定义如下: public interface IPeople { int Age { get; set; } string N ...
- ipmitool for windows下载网址
ipmitool for windows版本下载网址 http://ipmiutil.sourceforge.net/
- 网线接口调试,Android ADB网络调试!
ADB网络调试,网线接口调试 没有USB接口,照样可以调试,可通过网线接口调试步骤! 一.第一步连接WIFI 查看wifi 的IP win+R 键 打开运行 ,输入cmd 二.输入ipc ...