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. 2023-03-01 fatal: unable to access 'https://github.com/top-think/think/': OpenSSL SSL_read: Connection was reset, errno 10054

    问题描述:在thinkphp官网拉取tp5项目文件时报错: fatal: unable to access 'https://github.com/top-think/think/': OpenSSL ...

  2. OpenJ_Bailian - 1088

    OpenJ_Bailian - 1088 题解:DFS记忆化搜索 记忆化搜索也可以说是动态规划,最后的答案也是从一个个子问题推导而来 #include <bits/stdc++.h> #d ...

  3. BP神经网络及手工搭建神经网络

    import pandas as pd import numpy as np import matplotlib.pyplot as plt def sigmoid(x): # 定义网络激活函数 re ...

  4. https://github.com/wuweilin/springboot-login-demo

    wuweilin/springboot-login-demo: Springboot后端登录注册项目演示demo (github.com) jdk-8u172-windows-x64.exe apac ...

  5. .Net的产品变迁

    从开始接触.Net以来,转眼过了好几年.在这许多年里,不得不感慨.Net产品线也在不断发生着变化, 下面就简单的进行一下梳理. .Net能做桌面应用程序,也就是C/S,也能做网站开发,就是通常说的B/ ...

  6. The first python article

    Smile is the most beautiful language! and Python so on !

  7. 日志 LOG / Debug

    有很多时候我们想要查看日志文件,发现服务器已经被重启了,然后原来的日志就被打包存起来了,这个时候生成的gz日志文件我们就没有办法直接去查看了. 所以这个时候我们就需要zcat+日志名.gz来查看,还可 ...

  8. 記錄一下oracle数据库系统的comment數據字典(轉載)

    一.comment是oracle数据库系统的关键字,所以不能用来命名表明或字段名 二.comment关键字用于对表,字段添加注释,有利于用户对表结构以及数据库对象含义的理解. 三.用户可以通过数据字典 ...

  9. CentOS7 minimal 安装 VMware Tools(自带脚本安装)

    1.安装相关组件 yum -y install perl gcc make kernel-headers kernel-devel net-tools 2.新建挂载目录 mkdir -p /mnt/c ...

  10. centos6.5升级python3.6并安装boto3模块

    1.先升级openssl yum安装各种依赖,yum install gcc gcc-c++ autoconf automake zlib zlib-devel pcre-devel tar zxvf ...