题目大意:略

涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上

用$LCT$维护一个树上集合就好

因为它维护了树上集合,所以它别的啥都干不了了

发现树是静态的,可以用$dfs$序搞搞

把问题当成树上节点涂色会很麻烦

但只有相邻的不同颜色节点才会对答案产生影响

所以我们把涂色当成一种连边/断边操作

这样,问题就容易解决得多了

维护一个数组$f_{x}$表示$x$节点到根的路径上一共有$f_{x}$种颜色,$f_{x}-1$条断边

显然它的初始值就是节点x的深度

第一个操作,把这个位置到根打通

每断一条边,子树每个节点答案$+1$,连一条边,答案$-1$

在$access$操作中进行讨论即可

第二个操作,求链上不同颜色数量,即一个链的断边数量$-1$

显然,答案是$(f_{x}-1)+(f_{y}-1)-2*(f_{lca(x,y)}-1)+1=f_{x}+f_{y}-2*f_{lca(x,y)}+1$

即断边总数$+1$

不要把它当成节点的颜色去想

第三个操作,求子树内$f_{x}$最大值

以上操作皆可用$dfs$序+线段树实现!

随时保持清醒头脑,千万不要把这个$LCT$当成真正的$LCT$,它只是一个维护链集合的媒介!

尤其是断边/连边,进行区间修改操作时,需要找出开头/后继节点,而不是当前splay的根节点

 #include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 101000
#define S1 (N1<<1)
#define T1 (N1<<2)
#define ll long long
#define uint unsigned int
#define rint register int
#define ull unsigned long long
#define dd double
#define il inline
#define inf 1000000000
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int n,m,T;
struct Edge{
int to[N1*],nxt[N1*],head[N1],cte;
void ae(int u,int v)
{cte++;to[cte]=v,nxt[cte]=head[u],head[u]=cte;}
}E; struct SEG{
int ma[N1<<],tag[N1<<];
void pushup(int rt){ma[rt]=max(ma[rt<<],ma[rt<<|]);}
void pushdown(int rt)
{
if(!tag[rt]) return;
ma[rt<<]+=tag[rt]; ma[rt<<|]+=tag[rt];
tag[rt<<]+=tag[rt]; tag[rt<<|]+=tag[rt];
tag[rt]=;
}
void build(int *a,int *id,int l,int r,int rt)
{
if(l==r) {ma[rt]=a[id[l]];return;}
int mid=(l+r)>>;
build(a,id,l,mid,rt<<);
build(a,id,mid+,r,rt<<|);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt,int w)
{
if(!L||!R||L>R) return;
if(L<=l&&r<=R) {ma[rt]+=w,tag[rt]+=w;return;}
int mid=(l+r)>>; pushdown(rt);
if(L<=mid) update(L,R,l,mid,rt<<,w);
if(R>mid) update(L,R,mid+,r,rt<<|,w);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) return ma[rt];
int mid=(l+r)>>,ans=; pushdown(rt);
if(L<=mid) ans=max(ans,query(L,R,l,mid,rt<<));
if(R>mid) ans=max(ans,query(L,R,mid+,r,rt<<|));
return ans;
}
}s; namespace lct{
int ch[N1][],fa[N1];
int idf(int x){return ch[fa[x]][]==x?:;}
int isroot(int x){return (ch[fa[x]][]==x||ch[fa[x]][]==x)?:;}
//int stk[N1],tp;
void rot(int x)
{
int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
if(!isroot(y)) ch[ff][py]=x; fa[x]=ff;
fa[ch[x][px^]]=y,ch[y][px]=ch[x][px^];
ch[x][px^]=y,fa[y]=x;
//pushup(y),pushup(x);
}
void splay(int x)
{
int y=x; /*stk[++tp]=x;
while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];}
while(tp){pushdown(stk[tp--]);}*/
while(!isroot(x))
{
y=fa[x];
if(isroot(y)) rot(x);
else if(idf(y)==idf(x)) rot(y),rot(x);
else rot(x),rot(x);
}
}
int First(int x){while(ch[x][]) x=ch[x][];return x;}
int upper(int x){x=ch[x][];while(ch[x][]) x=ch[x][];return x;}
void access(int x,int *st,int *ed)
{
for(int y=,z;x;)
{
splay(x);
z=upper(x);
if(z) s.update(st[z],ed[z],,n,,);
z=First(y);
s.update(st[z],ed[z],,n,,-);
ch[x][]=y; y=x; x=fa[x];
}
}
void init(int *ff){
for(int i=;i<=n;i++) fa[i]=ff[i];
}
}; int fa[N1],son[N1],sz[N1],tp[N1],dep[N1];
int st[N1],ed[N1],id[N1],tot;
void dfs1(int u,int ff)
{
for(int j=E.head[u];j;j=E.nxt[j])
{
int v=E.to[j];
if(v==ff) continue;
dep[v]=dep[u]+; dfs1(v,u); fa[v]=u;
sz[u]+=sz[v]; son[u]=sz[v]>sz[son[u]]?v:son[u];
}
sz[u]++;
}
void dfs2(int u)
{
st[u]=ed[u]=++tot; id[tot]=u;
if(son[u]) tp[son[u]]=tp[u], dfs2(son[u]), ed[u]=max(ed[u],ed[son[u]]);;
for(int j=E.head[u];j;j=E.nxt[j])
{
int v=E.to[j];
if(v==fa[u]||v==son[u]) continue;
tp[v]=v; dfs2(v);
ed[u]=max(ed[u],ed[v]);
}
}
int lca(int x,int y)
{
while(tp[x]!=tp[y])
{
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
x=fa[tp[x]];
}
return dep[x]<dep[y]?x:y;
}
void mksame(int x)
{
lct::access(x,st,ed);
}
int split(int x,int y)
{
int sx,sy,sf,f=lca(x,y);
sx=s.query(st[x],st[x],,n,);
sy=s.query(st[y],st[y],,n,);
sf=s.query(st[f],st[f],,n,);
return sx+sy-*sf+;
}
int qmax(int x){return s.query(st[x],ed[x],,n,);}
void init()
{
dep[]=; dfs1(,-);
tp[]=; dfs2();
lct::init(fa);
s.build(dep,id,,n,);
} int qf(int x){return s.query(st[x],st[x],,n,);} int main()
{
scanf("%d%d",&n,&m);
int i,j,fl,x,y,cnt=,de;
for(i=;i<n;i++) x=gint(), y=gint(), E.ae(x,y), E.ae(y,x);
init();
for(j=;j<=m;j++)
{
fl=gint();
if(fl==){
x=gint();
mksame(x);
}else if(fl==){
x=gint(); y=gint();
printf("%d\n",split(x,y));
}else{
x=gint();
printf("%d\n",qmax(x));
}
}
return ;
}

BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)的更多相关文章

  1. [Sdoi2017]树点涂色 [lct 线段树]

    [Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...

  2. 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树

    [BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...

  3. 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

    树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...

  4. [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]

    题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...

  5. BZOJ 4817: [Sdoi2017]树点涂色 LCT+Access的性质+DFS序+线段树

    Code: #include<bits/stdc++.h> #define maxn 200003 #define inf -1000000 using namespace std; vo ...

  6. BZOJ4817[Sdoi2017]树点涂色——LCT+线段树

    题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...

  7. bzoj4817 & loj2001 [Sdoi2017]树点涂色 LCT + 线段树

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4817 https://loj.ac/problem/2001 题解 可以发现这个题就是 bzo ...

  8. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  9. BZOJ 4817 [Sdoi2017]树点涂色 ——LCT 线段树

    同BZOJ3779. SDOI出原题,还是弱化版的. 吃枣药丸 #include <map> #include <cmath> #include <queue> # ...

随机推荐

  1. redis实现集群加主从复制

    a)原理 (1)前提背景:如何解决redis横向扩展的问题----redis集群实现方式 (2)介绍redis 集群 ① Redis 集群是一个提供在多个Redis间节点间共享数据的程序集 ② 优势: ...

  2. useradd常用参数介绍

    -c :新账号passwd档的说明栏 -d :新账号每次登录时所使用的home_dir,预设值为default_home内login名称,并当成登录时目录名称 -e :*账号终止日期,日期的指定格式为 ...

  3. webKit 内核浏览器 源码分析

    如需转载,请注明出处! WebSite: http://www.jjos.org/ 作者: 姜江 linuxemacs@gmail.com QQ: 457283 这是一篇自己写于一年前的工作文档,分享 ...

  4. Java基础学习总结(61)——Java项目开发要注意的60个问题

    1. 首先写代码的时候最好不要有缺陷.最好的修复方法就是让 bug 胎死腹中. 良好的单元测试 强制数据库约束 使用输入验证框架 避免未实现的"else"条件 在应用到主程序之前知 ...

  5. CDH版本hadoop2.6伪分布式安装

    1.基础环境配置 主机名 IP地址 角色 Hadoop用户 centos05 192.168.48.105 NameNode.ResourceManager.SecondaryNameNode. Da ...

  6. yiii 数据库备份导出

    应用场景 数据对于网站来说 是非常重要的 一般 cms 后台 都有 数据备份功能.使用Yii 的第三方拓展 可以快速开发. spanjeta/yii2-backup spanjeta/yii2-bac ...

  7. BA-Honeywell WEBsAX系统

  8. BA-siemens-insight在win7下如何配置opc接口

    一.运行环境:win7(OPC接口在win_xp下配置需安装插件,不好意思没搞定,现在只有win7系统32位下的教程了) 由于OPC(OLE for Process Control)建立在Micros ...

  9. 解决was6版本号过期问题

    原创作品.出自 "深蓝的blog" 博客,欢迎转载.转载时请务必注明出处.否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlong ...

  10. UML基本架构建模--获取类

     Getting Started 開始 Modeling a system involves identifying the things that are important to your p ...