题目大意

有一棵\(n\)(\(n\leq10^5\))个节点的树,每个点有颜色\(c\),一开始所有颜色互不相同

要进行\(m\)(\(m\leq10^5\))次操作,每次操作是以下三种中的一种:

1.给出点\(x\),将点\(x\)到根路径上所有点的染成一种没出现过的颜色

2.给出点\(x\),\(y\),询问点\(x\)到\(y\)的简单路径上有多少种颜色

3.给出点\(x\),询问点\(x\)的子树中到根路径上颜色种类最多的点

题解

把1操作看成LCT的access操作,2操作就相当于询问一条链上有几条LCT里的重链,3操作相当于询问子树中到根LCT重链中最多的点

同时维护LCT和树剖,LCT为树的染色状态(同色的点在同一条重链上),树剖维护每个点\(i\)到根有几条重链,记为\(a_i\)

1操作就是LCT的access,同时树剖修改\(a_i\)

2操作的答案是\(a_x+a_y-2*a_{lca(x,y)}+1\),不用考虑重链在\(lca(x,y)\)处拐弯的情况

3操作是查询子树里\(a_i\)的最小值

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define maxn 100010
#define maxm (maxn<<1)
#define view(u,k) for(int k=fir[u];k!=-1;k=nxt[k])
#define ls (u<<1)
#define rs (u<<1|1)
#define ls2 son[u][0]
#define rs2 son[u][1]
#define mi (l+r>>1)
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
int fir[maxn],nxt[maxm],v[maxm],now,n,q;
int siz[maxn],dfn[maxn],top[maxn],fth[maxn],wson[maxn],dep[maxn],cnt,tim,to[maxn],tr[maxn<<2],mk[maxn<<2];
int fa[maxn],son[maxn][2],rev[maxn],st[maxn],tp,tmpdep[maxn];
void ade(int u1,int v1){v[cnt]=v1,nxt[cnt]=fir[u1],fir[u1]=cnt++;}
void getson(int u)
{
siz[u]=1;
view(u,k)if(v[k]!=fth[u])
{
fa[v[k]]=fth[v[k]]=u,tmpdep[v[k]]=tmpdep[u]+1,dep[v[k]]=dep[u]+1,getson(v[k]),siz[u]+=siz[v[k]];
if(siz[v[k]]>siz[wson[u]])wson[u]=v[k];
}
}
void gettop(int u,int anc)
{
dfn[u]=++tim,to[tim]=u,top[u]=anc;
if(wson[u])gettop(wson[u],anc);
view(u,k)if(v[k]!=fth[u]&&v[k]!=wson[u])gettop(v[k],v[k]);
}
void build(int u,int l,int r)
{
if(l==r){tr[u]=dep[to[l]]+1;return;}
build(ls,l,mi),build(rs,mi+1,r),tr[u]=max(tr[ls],tr[rs]);return;
}
void mark(int u,int k){tr[u]+=k,mk[u]+=k;}
void pd(int u){if(mk[u]){mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}}
void add(int u,int l,int r,int x,int y,int k)
{
if(x<=l&&r<=y)return mark(u,k);
pd(u);
if(x<=mi)add(ls,l,mi,x,y,k);
if(y>mi)add(rs,mi+1,r,x,y,k);
tr[u]=max(tr[ls],tr[rs]);
return;
}
int ask(int u,int l,int r,int x,int y)
{
if(x<=l&&r<=y)return tr[u];
pd(u);
int res=0;
if(x<=mi)res=ask(ls,l,mi,x,y);
if(y>mi)res=max(res,ask(rs,mi+1,r,x,y));
return res;
}
int getso(int u){return son[fa[u]][0]!=u;}
int nort(int u){return son[fa[u]][0]==u||son[fa[u]][1]==u;}
void rot(int u)
{
int fu=fa[u],ffu=fa[fu],l=getso(u),fl=getso(fu),r=l^1,rson=son[u][r];
if(nort(fu))son[ffu][fl]=u;son[fu][l]=rson,son[u][r]=fu,fa[rson]=fu,fa[u]=ffu,fa[fu]=u;
}
void splay(int u)
{
while(nort(u)){int fu=fa[u];if(nort(fu))rot(getso(u)^getso(fu)?u:fu);rot(u);}
}
int rnxt(int u){u=rs2;while(u){if(!ls2)break;u=ls2;}return u;}
int sroot(int u){while(u&&ls2)u=ls2;return u;}
void acs(int u)
{
for(int vv=0;u;vv=u,u=fa[u])
{
splay(u);
int tmp=rnxt(u),tmp2=sroot(vv);
rs2=vv;
if(tmp){add(1,1,n,dfn[tmp],dfn[tmp]+siz[tmp]-1,1);}
if(tmp2){add(1,1,n,dfn[tmp2],dfn[tmp2]+siz[tmp2]-1,-1);}
}
}
int Lca(int x,int y)
{
while(top[x]!=top[y])
{
if(tmpdep[top[x]]<tmpdep[top[y]])swap(x,y);
x=fth[top[x]];
}
return tmpdep[x]<tmpdep[y]?x:y;
}
int main()
{
n=read(),q=read();
memset(fir,-1,sizeof(fir));
rep(i,1,n-1){int x=read(),y=read();ade(x,y),ade(y,x);}
getson(1),gettop(1,1),build(1,1,n);
while(q--)
{
int f=read();
if(f==1){int x=read();acs(x);}
else if(f==2)
{
int x=read(),y=read(),lca=Lca(x,y),ansx=ask(1,1,n,dfn[x],dfn[x]),ansy=ask(1,1,n,dfn[y],dfn[y]),ansl=ask(1,1,n,dfn[lca],dfn[lca]);
write(ansx+ansy-2*ansl+1);
}
else
{
int x=read();
write(ask(1,1,n,dfn[x],dfn[x]+siz[x]-1));
}
}
return 0;
}

并不对劲的bzoj4817:loj2001:p3703:[SDOI2017]树点涂色的更多相关文章

  1. P3703 [SDOI2017]树点涂色

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

  2. Luogu P3703 [SDOI2017]树点涂色

    比较有趣的综合树上问题,刷LCT题单时做的但是发现后面LCT只是起了辅助作用233 首先我们分析每一个操作,\(1\)的定义就让我们联想到了access,我们回忆一下LCT的性质: LCT中每一个sp ...

  3. 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)

    洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...

  4. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

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

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

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

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

  7. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

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

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

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

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

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

随机推荐

  1. mapStruct笔记

    背景 mapStruct 是一个方便对象转换的工具,类似的工具还有 Dozer, BeanUtils. 实现 mapStruct的核心是在编译期生成基于转换规则的 Impl 文件,运行时直接调用 Im ...

  2. CodeVs1519 过路费

    题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府修建了m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市T需要收取的过路费 ...

  3. [codeVS1204] 单词背诵

    题目描述 灵梦有n个单词想要背,但她想通过一篇文章中的一段来记住这些单词. 文章由m个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个).并且在背诵的单词量尽量多的情 ...

  4. Codevs 1688 求逆序对

     时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我 ...

  5. P3366 最小生成树【模板】 洛谷

    https://www.luogu.org/problem/show?pid=3366 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包 ...

  6. HDU 1024 【DP】

    题意: 给n个数将其分成连续的m组,使得这些组的数加和最大,组与组之间可以空数. /* dp[i][j]表示将前j个数分成i个组最大值 状态转移方程是: dp[i][j]=max(dp[i-1][0. ...

  7. css三大布局

    标准流: 从左到右,从上到下块级元素独占一行,行内元素碰到父盒子边缘换行 浮动: 特点 1 元素浮动之后不占据原来的位置(脱标),变成立体,下面可以有东西,只影响下面的 2 浮动的盒子在一行上显示 3 ...

  8. Java后端技术书单

    写博客记录技术上使用的各种问题,这个只能算是一个打游击. 如果要把一个知识学透,最有效的方式就是系统学习,而系统学习就是看书,书本上有清晰的学习路线以及相应的技术栈. 下面是我收集的Java后端的技术 ...

  9. Java子类重写父类方法注意问题收集(转)

    子类不能重写父类的静态方法,私有方法.即使你看到子类中存在貌似是重写的父类的静态方法或者私有方法,编译是没有问题的,但那其实是你重新又定义的方法,不是重写.具体有关重写父类方法的规则如下: 重写规则之 ...

  10. 关于MySQL的boolean和tinyint(1)

    原文:http://blog.csdn.net/woshixuye/article/details/7089508 MySQL保存boolean值时用1代表TRUE,0代表FALSE.boolean在 ...