传送门

Description

Bob 有一棵\(n\)个点的有根树,其中\(1\)号点是根节点。Bob 在每个节点上涂了颜色,并且每个点上的颜色不同。

定义一条路径的权值是,这条路径上的点(包括起点和终点)共有多少种不同的颜色。

Bob 可能会进行这几种操作:

  • 1 x,把点\(x\)到根节点的路径上的所有的点染上一种没有用过的新颜色;
  • 2 x y,求 \(x\) 到 \(y\) 的路径的权值;
  • 3 x,在以 \(x\) 为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

Bob 一共会进行 \(m\) 次操作。

Solution

  1. 发现任何时刻,每种颜色都是一条链,考虑直接用lct维护,1 x就等同于access x

  2. 发现每次1 x操作时,修改的是若干个子树的\(ans\),线段树维护\(dfs\)上的答案

    access经过轻边是,对线段树进行区间修改即可

  3. 祖先答案中的颜色,必然出现在孩子的答案中,所以路径的答案可以看成是:

    \[ans_x+ans_y-2*ans_{lca(x,y)}+1
    \]

  4. 一个子树的答案直接区间求最值即可

Code 

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define reg register
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MN=1e5+5;
int N,M,L[MN],R[MN],dep[MN],fdfn[MN];
class Seg
{
int lazy[MN<<2],t[MN<<2];
void C(int x,int y){t[x]+=y;lazy[x]+=y;}
void down(int x){if(lazy[x])C(x<<1,lazy[x]),C(x<<1|1,lazy[x]),lazy[x]=0;}
void Modi(int x,int l,int r,int a,int b,int ad)
{
if(l==a&&r==b){C(x,ad);return;}
reg int mid=(l+r)>>1;down(x);
if(b<=mid)Modi(x<<1,l,mid,a,b,ad);
else if(a>mid)Modi(x<<1|1,mid+1,r,a,b,ad);
else Modi(x<<1,l,mid,a,mid,ad),Modi(x<<1|1,mid+1,r,mid+1,b,ad);
t[x]=max(t[x<<1],t[x<<1|1]);
}
int Q1(int x,int l,int r,int a,int b)
{
if(l==a&&r==b)return t[x];
reg int mid=(l+r)>>1;down(x);
if(b<=mid)return Q1(x<<1,l,mid,a,b);
else if(a>mid)return Q1(x<<1|1,mid+1,r,a,b);
else return max(Q1(x<<1,l,mid,a,mid),Q1(x<<1|1,mid+1,r,mid+1,b));
}
public:
void Build(int x,int l,int r)
{
if(l==r) return (void)(t[x]=dep[fdfn[l]]);
reg int mid=(l+r)>>1;
Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
t[x]=max(t[x<<1],t[x<<1|1]);
}
void md(int x,int ad){if(x)Modi(1,1,N,L[x],R[x],ad);}
int q(int x){return Q1(1,1,N,L[x],L[x]);}
int _q(int x){return Q1(1,1,N,L[x],R[x]);}
}T;
class Link_Cut_Tree
{
int fa[MN],c[MN][2];
bool nrt(int x){return c[fa[x]][0]==x||c[fa[x]][1]==x;}
bool get(int x){return c[fa[x]][1]==x;}
void rtt(int x)
{
int y=fa[x],z=fa[y],l=get(x),r=l^1;if(nrt(y))c[z][get(y)]=x;fa[x]=z;
fa[c[x][r]]=y;c[y][l]=c[x][r];fa[y]=x;c[x][r]=y;
}
void Splay(int x)
{
for(;nrt(x);rtt(x))
if(nrt(fa[x])) rtt(get(fa[x])^get(x)?x:fa[x]);
}
int fir(int x){if(!x) return 0;while(c[x][0])x=c[x][0];return x;}
public:
void acs(int x){reg int i;for(i=0;x;x=fa[i=x])Splay(x),T.md(fir(c[x][1]),1),c[x][1]=i,T.md(fir(i),-1);}
void link(int x,int y){fa[x]=y;}
}lct;
class Tree
{
int fa[MN],mx[MN],siz[MN],top[MN],ind;
std::vector<int> A[MN];
void dfs1(int x,int f)
{
reg int i;siz[x]=1;fa[x]=f;lct.link(x,f);dep[x]=dep[f]+1;
for(i=A[x].size()-1;~i;--i)if(A[x][i]^f)
dfs1(A[x][i],x),siz[x]+=siz[A[x][i]],siz[A[x][i]]>siz[mx[x]]?mx[x]=A[x][i]:0;
}
void dfs2(int x,int tp)
{
L[x]=++ind;fdfn[ind]=x;top[x]=tp;if(mx[x])dfs2(mx[x],tp);reg int i;
for(i=A[x].size()-1;~i;--i)if(A[x][i]!=fa[x]&&A[x][i]!=mx[x])dfs2(A[x][i],A[x][i]);
R[x]=ind;
}
public:
void ins(int x,int y){A[x].push_back(y);A[y].push_back(x);}
void build(){dfs1(1,0);dfs2(1,1);}
int lca(int x,int y)
{
while(top[x]^top[y])
dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
return dep[x]<dep[y]?x:y;
}
}tree;
int main()
{
N=read();M=read();
reg int i,opt,x,y;
for(i=1;i<N;++i) x=read(),tree.ins(x,read());
tree.build();T.Build(1,1,N);
while(M--)
{
opt=read(),x=read();
if(opt==1)lct.acs(x);
if(opt==2)y=read(),printf("%d\n",T.q(x)+T.q(y)+1-2*T.q(tree.lca(x,y)));
if(opt==3)printf("%d\n",T._q(x));
}
return 0;
}

Blog来自PaperCloud,未经允许,请勿转载,TKS!

[sdoi 2017]树点涂色的更多相关文章

  1. [BZOJ 4817] [SDOI 2017] 树点涂色

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

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

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

  3. 「SDOI2017」树点涂色 解题报告

    「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...

  4. P3703 [SDOI2017]树点涂色

    P3703 [SDOI2017]树点涂色 链接 分析: 首先对于询问,感觉是线段树维护dfs序,每个点记录到根的颜色个数.第二问差分,第三问区间取max. 那么考虑修改,每次将一个点的颜色变成和父节点 ...

  5. 【LG3703】[SDOI2017]树点涂色

    [LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...

  6. 【BZOJ4817】树点涂色(LCT,线段树,树链剖分)

    [BZOJ4817]树点涂色(LCT,线段树,树链剖分) 题面 BZOJ Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义 ...

  7. [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status ...

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

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

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

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

随机推荐

  1. 服务发现框架选型: Consul、Zookeeper还是etcd ?

    背景 本文并不介绍服务发现的基本原理.除了一致性算法之外,其他并没有太多高深的算法,网上的资料很容易让大家明白上面是服务发现.想直接查看结论的同学,请直接跳到文末.目前,市面上有非常多的服务发现工具, ...

  2. 第一阶段:Java基础 1.JAVA开发介绍---6. Java基本数据类型

    Java 的两大数据类型: 内置数据类型(基本数据类型) 引用数据类型 本数据类型: Java语言提供了八种基本类型.六种数字类型,一种字符类型,还有一种布尔型. byte,short,int,lon ...

  3. Java之路---Day12(多态)

    2019-10-26-22:40:09 目录: 1.多态的概念 2.多态的分类 3.实现多态的三个必要条件 4.多态的格式 5.多态成员变量的使用特点 6.多态成员方法的使用特点 7.多态的好处 8. ...

  4. [摘抄] 3.AMD规范与CommonJS规范的兼容性

    3. AMD规范与CommonJS规范的兼容性 CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作. AMD规范则是非同步加载模块,允许指定回调函数. 由于Node.js ...

  5. 去除vue项目地址栏中的#

    在router文件夹下的index.js中的router实例中添加mode属性,值设置为history export default new Router({ mode:"history&q ...

  6. mysql 获取指定日期到指定日期 区间段的日期

    第一种方法: cross join (就相当于mysql中的循环) CROSS JOIN 把两张表中的数据进行 N * M的组合,即笛卡尔积 这里的两张表利用 union all都有5条数据,所以进行 ...

  7. JavaScript 流程控制(一)顺序结构与分支结构

    语句:语句可以理解为一个行为,循环语句和判断语句就是典型的语句.一个程序有很多个语句组成,一般情况下分号;分割一个一个的语句:如果省略分号,则由解析器确定语句的结尾(不推荐使用) 一.流程控制 流程控 ...

  8. Java 面向对象—杂项(方法不能重写,修饰符,变量)

    一.哪些方法不能被重写? 1.final 修饰的不能重写 2.static 修饰的不能重写 3.private 修饰的,因为私有的在子类中不可见 4.如果跨包的话,修饰符缺省的也不能被重写,因为缺省的 ...

  9. 【Spring Cloud】Spring Cloud之Zipkin server搭建以及RabbitMQ收集,分布式服务跟踪(3)

    一.搭建步骤 1)新建Spring Boot项目,引入pom坐标 <parent> <groupId>org.springframework.boot</groupId& ...

  10. Mac开源文本编辑器Brackets 快捷操作有哪些?

    Brackets for Mac是一款可靠,直观且易于使用的macOS应用程序,可用作HTML,CSS和JavaScript项目的代码编辑器.如果你能了解更多Mac开源文本编辑器Brackets 快捷 ...