Description

Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
1 x:
把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
2 x y:
求x到y的路径的权值。
3 x
在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
Bob一共会进行m次操作 

Input

第一行两个数n,m。
接下来n-1行,每行两个数a,b,表示a与b之间有一条边。
接下来m行,表示操作,格式见题目描述
1<=n,m<=100000

Output

每当出现2,3操作,输出一行。
如果是2操作,输出一个数表示路径的权值
如果是3操作,输出一个数表示权值的最大值

题解:

和事情的相似度那道题挺像的.
都是利用 $LCT$ 中同一颗 $splay$ 中颜色相等这个性质.
这道题用线段树维护一下 DFS 序,查询的时候在 DFS 序中查询即可.
维护每个点到根节点的色块个数.
考虑染色时会产生的影响:
假设现在要把某个点到根节点路径都染成蓝色.
当前 $Access$ 时处理的点为  $x$,右儿子为 $rson$,要连接的为 $y$
那么,对于 $y$ 及其子树来说,原来有红 + 蓝,现在将只有蓝,答案减一
对于 $rson$ 及其子树来说,原来只有红,现在有红 + 蓝( $rson$ 没被染成蓝色)
对于子树权值修改,直接上线段树即可.
 

#include<bits/stdc++.h>
#define maxn 200003
#define inf -1000000
using namespace std;
void setIO(string s)
{
string in=s+".in",out=s+".out";
freopen(in.c_str(),"r",stdin);
freopen(out.c_str(),"w",stdout);
}
int tim,edges,n,Q,_curcol;
int dfn[maxn],ln[maxn],fa[maxn],hd[maxn],to[maxn<<1],nex[maxn<<1];
int st[maxn],ed[maxn],top[maxn],hson[maxn],siz[maxn],dep[maxn];
void addedge(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
namespace tr
{
int maxv[maxn<<2],lazy[maxn<<2];
void mark(int x,int k)
{
lazy[x]+=k, maxv[x]+=k;
}
void pushdown(int l,int r,int x)
{
if(!lazy[x]) return;
int mid=(l+r)>>1;
if(mid>=l) mark(x<<1,lazy[x]);
if(r>mid) mark((x<<1)|1,lazy[x]);
lazy[x]=0;
}
void update(int l,int r,int x,int L,int R,int k)
{
if(l>=L&&r<=R)
{
mark(x,k);
return;
}
pushdown(l,r,x);
int mid=(l+r)>>1;
if(L<=mid) update(l,mid,x<<1,L,R,k);
if(R>mid) update(mid+1,r,(x<<1)|1,L,R,k);
maxv[x]=max(maxv[x<<1],maxv[(x<<1)|1]);
}
int query(int l,int r,int x,int L,int R)
{
if(l>=L&&r<=R) return maxv[x];
pushdown(l,r,x);
int mid=(l+r)>>1, tmp=inf;
if(L<=mid) tmp=max(tmp,query(l,mid,x<<1,L,R));
if(R>mid) tmp=max(tmp,query(mid+1,r,(x<<1)|1,L,R));
return tmp;
}
int po(int l,int r,int x,int k)
{
if(l==r) return maxv[x];
int mid=(l+r)>>1;
pushdown(l,r,x);
if(k<=mid) return po(l,mid,x<<1,k);
else return po(mid+1,r,(x<<1)|1,k);
}
};
namespace tree
{
#define lson ch[x][0]
#define rson ch[x][1]
#define get(x) (ch[f[x]][1]==x)
#define isrt(x) (!(ch[f[x]][0]==x||ch[f[x]][1]==x))
int ch[maxn][2],f[maxn],col[maxn],sta[maxn];
void pushdown(int x)
{
if(!x) return;
if(col[x])
{
if(lson) col[lson]=col[x];
if(rson) col[rson]=col[x];
}
}
int findrt(int x)
{
while(lson)x=lson;
return x;
}
void rotate(int x)
{
int old=f[x],fold=f[old],which=get(x);
if(!isrt(old)) ch[fold][ch[fold][1]==old]=x;
ch[old][which]=ch[x][which^1], f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=fold;
}
void splay(int x)
{
int u=x,v=0,fa;
sta[++v]=u;
while(!isrt(u)) sta[++v]=f[u],u=f[u];
while(v) pushdown(sta[v--]);
for(u=f[u];(fa=f[x])!=u;rotate(x))
if(f[fa]!=u)
rotate(get(fa)==get(x)?fa:x);
}
void Access(int x,int co)
{
int t=0,son;
while(x)
{
splay(x);
if(t) son=findrt(t), tr::update(1,n,1,st[son],ed[son],-1);
if(rson) son=findrt(rson),tr::update(1,n,1,st[son],ed[son],1);
col[x]=co,rson=t,t=x,x=f[x];
}
}
};
void dfs1(int u,int ff)
{
fa[u]=ff;
siz[u]=1;
dep[u]=dep[ff]+1;
ln[++tim]=u;
dfn[u]=st[u]=tim;
tr::update(1,n,1,dfn[u],dfn[u],dep[u]);
tree::f[u]=ff;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[hson[u]]) hson[u]=v;
}
ed[u]=tim;
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(hson[u]) dfs2(hson[u],tp);
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==hson[u]||v==fa[u]) continue;
dfs2(v,v);
}
}
int LCA(int x,int y)
{
while(top[x]^top[y]) dep[top[x]] < dep[top[y]] ? y = fa[top[y]] : x = fa[top[x]];
return dep[x] < dep[y] ? x : y;
}
int main()
{
// setIO("input");
scanf("%d%d",&n,&Q);
tr::maxv[0]=inf;
for(int i=1,u,v;i<n;++i)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs1(1,0);
dfs2(1,1);
int opt,x,y,lca,ou=0;
while(Q--)
{
scanf("%d",&opt);
switch(opt)
{
case 1 :
{
scanf("%d",&x);
tree::Access(x,++_curcol);
break;
}
case 2 :
{
scanf("%d%d",&x,&y);
lca=LCA(x,y);
ou=0;
ou+=tr::po(1,n,1,dfn[x]);
ou+=tr::po(1,n,1,dfn[y]);
ou-=tr::po(1,n,1,dfn[lca])<<1;
ou+=1;
printf("%d\n",ou);
break;
}
case 3 :
{
scanf("%d",&x);
printf("%d\n",tr::query(1,n,1,st[x],ed[x]));
break;
}
}
}
return 0;
}

  

BZOJ 4817: [Sdoi2017]树点涂色 LCT+Access的性质+DFS序+线段树的更多相关文章

  1. BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)

    题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...

  2. DFS序+线段树(bzoj 4034)

    题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...

  3. BZOJ 3252题解(贪心+dfs序+线段树)

    题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...

  4. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  5. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  6. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  7. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  8. POJ 3321 DFS序+线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include < ...

  9. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

随机推荐

  1. 快速傅立叶变换&HDU 1402

    参考http://www.cnblogs.com/v-July-v/archive/2011/08/13/2214132.html <算导> 那么,更快速的多项式乘法就依赖于能否把一个系数 ...

  2. C++对象模型——对象复制语意学 (Object Copy Semantics)(第五章)

    5.3    对象复制语意学 (Object Copy Semantics) 当设计一个 class,并以一个 class object指定给 class object时,有三种选择:     1.什 ...

  3. spring 计时器

    spring 计时器 可以这样: http://blog.csdn.net/u010648555/article/details/52162840 也可以使用annotation <!-- 设置 ...

  4. 把握linux内核设计思想系列

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 本专栏分析linux内核的设计实现,包含系统调用.中断.下半部机制.时间管理. ...

  5. NTC 家电中的应用1

    NTC应用非常广,特别是家电产品中,基本上凡是涉及到温度控制的都会选择它.本人应用的的产品有打奶器.电烤箱,油炸锅,咖啡机,直发器,暖风机和电壁炉,尽管应用广.但都是千篇一律.当中最基本的要点是应用中 ...

  6. ASP环境下轻松实现报表的打印 (转)

    作者:zcg2000 一.前言 ASP在电子商务上应用广泛,报表的处理又有一些麻烦.本文介绍了在ASP中利用 本人写的Report Server Page脚本解释器实现报表的显示.打印. 二.准备工作 ...

  7. 从头认识java-15.2 Collection的经常用法(2)-注意点

    上一章节我们讲述了Collection的经常用法.还有之前的章节我们介绍了Collection的addAll方法,这一章节我们介绍一下它的注意点. 注意点就是,在经常用法里面,基本都是可选操作. 什么 ...

  8. 1360 xth 的玫瑰花

    1360 xth 的玫瑰花  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 这天是rabbit 的生日 ...

  9. user和userdebug区别

    user:不可以root userdebug:可以root

  10. codeforces 915D Almost Acyclic Graph 拓扑排序

    大意:给出一个有向图,问能否在只去掉一条边的情况下破掉所有的环 解析:最直接的是枚举每个边,将其禁用,然后在图中找环,如果可以就YES,都不行就NO 复杂度O(N*M)看起来不超时 但是实现了以后发现 ...