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的更多相关文章

  1. [BZOJ 4573][ZJOI 2016]大森林

    [LOJ 2092][BZOJ 4573][UOJ 195][ZJOI 2016]大森林 题意 给定一个树序列, 初始时所有树都只有一个点, 要求支持三种操作: 区间种树(在某个特定点上长出一个子结点 ...

  2. bzoj 4573 大森林

    bzoj 4573 大森林 由于树上路径是唯一的,查询合法的两个点间路径长度显然与其他加点操作无关,所以可以离线处理,将所有的查询放在加点后. 这样我们可以对每棵树都在上颗树的基础上处理好形态后,处理 ...

  3. bzoj 4573: [Zjoi2016]大森林 lct splay

    http://www.lydsy.com/JudgeOnline/problem.php?id=4573 http://blog.csdn.net/lych_cys/article/details/5 ...

  4. 【刷题】BZOJ 4573 [Zjoi2016]大森林

    Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力.小 ...

  5. bzoj 4573: [Zjoi2016]大森林

    Description 小Y家里有一个大森林,里面有n棵树,编号从1到n.一开始这些树都只是树苗,只有一个节点,标号为1.这些树 都有一个特殊的节点,我们称之为生长节点,这些节点有生长出子节点的能力. ...

  6. 【总结】Link-Cut Tree

    这是一篇关于LCT的总结 加删边的好朋友--Link Cut Tree Link-Cut Tree,LCT的全称 可以说是从树剖引出的问题 树剖可以解决静态的修改或查询树的链上信息:那如果图会不断改变 ...

  7. BZOJ 1051 受欢迎的牛(Tarjan缩点)

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4573  Solved: 2428 [Submit][S ...

  8. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  9. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  10. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

随机推荐

  1. IBM免费服务器试用

    IBM公司的免费资源,仅需一个邮箱就可以注册申请,注册可以有60天试用期. 1.注册 点击 注册进入IBM教育资源官网进行注册,注册时仅需要一个有效邮箱,QQ,Gmail,outlook均可. 注册邮 ...

  2. Centos 7 环境 安装todesk异常

    按照todesk官网安装步骤安装. 其实就两步就完成了,在自己虚拟机centos7环境下测试一切正常,但正式环境centos7.9环境下能安装,但安装完打不开,感觉是内核版本的问题. Todesk-- ...

  3. Python的入门学习Day 22~24——form”夜曲编程“

    Day 22 time:2021.8.19. ​ 顺着歌曲的旋律,内心一下子就安静了呢.终于,我可以好好写日记了,徜徉在一片金色的花海里.今天主要学习了匿名函数.这是一种很有趣的函数呢,像孙悟空会72 ...

  4. 微信小程序图片和签名

    图片上传功能 chooseImage(e) { wx.chooseImage({ sizeType: ['original', 'compressed'], //可选择原图或压缩后的图片 source ...

  5. uniapp输入空格

    uniapp   密码框输入空格(去除空格)的时候一直回显不及时  经过一番折腾 终于搞定 1.先赋值:     this.pwd = e.detail.value 2. 使用setTimeout(再 ...

  6. 抽取JDBC工具类:JDBCUtils

    目的:简化书写 分析:     驱动注册,连接对象创建,其中包括输入驱动,数据库的地址,以及用户名和密码,每次编写代码都需要重复编写,如果每次使用的都是同一个账户的同一个数据库,代码的重复读很高,甚至 ...

  7. 软件工程日报七——checkbox的使用

    今天学了checkbox的使用 activity_main.xml文件为 <?xml version="1.0" encoding="utf-8"?> ...

  8. K8S-pod详解

    目录: namespace六大类型 Pod基础概念 Pod两种使用方式 通常把Pod分为两类 Pod容器的分类 init的容器作用 镜像拉取策略(image PullPOlicy) 部署harbor创 ...

  9. COMMON_FUNC_SPLIT_STRING

    void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& ...

  10. python_lib_0001_decorator_print_log

    def decorator_log_funcname( func ):     def wrapper(*arg, **kw):         print("")         ...