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] ...
随机推荐
- htmlApk:一个轻松在线打包生成双端app应用的网站
htmlApk平台,基于HTML打包制作APP,只要有手机网站或者HTML文件,3分钟即可生成app多端应用,同时拥有苹果版和安卓版双系统APP,快速进入移动互联时代. 全面支持h5网址打包,可设置图 ...
- cpp chrono basic
// cpp 20 //c++ - Number of seconds since midnight - Stack Overflow //https://stackoverflow.com/ques ...
- C# Socket 通信
C# Socket通信 Socket通信主要分为两部分,服务端和客户端,其中服务端和客户端都具有接收消息和发送消息的功能,具体通信流程就是服务端先去监听一个端口号,等待客户端的连接,客户端通过指定IP ...
- top单核与32C--CPU爆表
linux的cpu使用频率是根据cpu个数和核数决定的 top, 然后你按一下键盘的1,这就是单个核心的负载,不然是所有核心的负载相加,自然会超过100 单核为100%,服务器是32核的,下面基本用了 ...
- 配置Centos8网络绑定
配置Centos8网络绑定 原理: 在物理网卡两块之上创建一块虚拟主卡, 逻辑上是一主双从, 按不同的模式负载运行,常用模式如主备或并行提供双倍带宽等.模式: 可选参数"mode=act ...
- C# 抽象类小谈
最近在做一个测试系统,就是读取功率计上的数据,在上位机软件上显示出来. 电脑界面不是我们这次的主讲就略过,我们这里主要讲一个类的实现. 最开始领导给了一个 远方的三相功率计 给我让我写上位机,很简单, ...
- 关于邮箱怎么验证是不是真实的企业邮箱(java汉字和英文呼唤)
企业邮箱的域名一般都是zhangsan@公司域名,或者zhang_san@公司域名这种形式.这里我只列举zhangsan@公司域名这种形式. 公司要我做一个企业邮箱的模糊匹配和验证,刚接到以为很难.结 ...
- HiveServer2启动报TezConfiguration类NoClassDefFoundError错误
错误信息如下: 2021-01-03 20:11:26,355 WARN [main] server.HiveServer2: Error starting HiveServer2 on attemp ...
- schemer校验器的简单应用
from schemer import Schema def func(account, password): request_params = { 'account': account, 'pass ...
- List list = new ArrayList()为何父类引用指向子类对象(多态)
转自--https://blog.csdn.net/Jae_Peng/article/details/80151033 不习惯用csdn,博客园没有搜到类似的,摘录过来. 多态:要有继承,方法的重写, ...