题目大意

有一棵\(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. Leetcode 230.二叉搜索树第k小的数

    二叉搜索树第k小的数 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 说明:你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数. 示例 1: 输 ...

  2. [NOIP1998] 提高组 洛谷P1011 车站

    题目描述 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人.从第3站起( ...

  3. Linux硬件监控

    https://blog.csdn.net/qq_30353203/article/details/62222882

  4. 2015轻院校赛 B 迷宫 (bfs)

    http://acm.zznu.edu.cn/problem.php?id=1967 这套题的有毒   我交了好多遍才对 坑:机关要按照顺序走 并且在走这个机关之前不能走这个机关  但是能穿过这个机关 ...

  5. Java模拟斗地主(实现大小排序)

    import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Li ...

  6. 使用图像扫描控件ScanOnWeb实现在线图像扫描

    今天上网查资料,看到一篇文章,描述的是一个开发OA软件的公司解决浏览器嵌入式扫描仪编程的文章,文章描述了改OA厂商的工程师如何辛苦的克服了各种技术难题,最终实现了在线图像扫描处理,然后又在无数个不眠的 ...

  7. POJ 3488 &amp; HDU 1915 Arne Saknussemm(模拟)

    题目链接: POJ:http://poj.org/problem? id=3488 HDU:pid=1915">http://acm.hdu.edu.cn/showproblem.ph ...

  8. Visual Studio Visual assistant注释也做拼写检查怎么办

    1 打开Visual Assistant   2 在Advanced中找到Underlines,取消勾选"Underline spelling errors in comments and ...

  9. Nerv --- React IE8 兼容方案

    创建项目 创建一个目录,使用npm快速初始化 $ mkdir my-project && npm init -y 安装依赖 安装webpack以及babel $ npm install ...

  10. smartfoxserver扩展里面过滤聊天的不合法字符

    http://blog.csdn.net/yc7369/article/details/35567105 近期做手游客户要求加上一个聊天功能.事实上嘛,个人认为这个聊天功能比較鸡肋,这部分差点儿已经有 ...