题目大意

有一棵\(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. 【组合 数学】codeforces C. Do you want a date?

    codeforces.com/contest/810/problem/C [题意] 给定一个集合A,求 , 输入: [思路] 基数为n的集合有2^n-1个非空子集. 首先n个数要从小到大排序,枚举最后 ...

  2. VirtualBox - 虚拟机下主机与虚拟机、虚拟机与虚拟机之间通信配置

    看了一下网上别人写的文章:http://www.it165.net/os/html/201401/7063.html 文章里面使用的是Debian,我这里配置的虚拟机系统一个是Ubuntu 14.10 ...

  3. CodeForces - 356A Knight Tournament

    http://codeforces.com/problemset/problem/356/A 首先理解题意 每次给出l 和r  在l - r之间还有资格的选手中得出一个胜者 暴力思路: 首先维护还有资 ...

  4. phpstorm的破解

    按照PHPstorm进入如下页面: 然后继续单击License  server  输入:http://www.0-php.com:1017    PHPstorm完美运行!!!!!

  5. wordpress优化:Gravatar头像被墙及解决方案

    网站缓存现象: 打开网站是左下角出现0.gravatar.com.1.gravatar.com或2.gravatar.com字样,网站一直处于缓存状态,迟迟未能打开.很多人都会缺乏耐心地等待一个网页的 ...

  6. CodeForces 599B Spongebob and Joke

    简单题. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> ...

  7. dsu on tree:关于一类无修改询问子树可合并问题

    dsu on tree:关于一类无修改询问子树可合并问题 开始学长讲课的时候听懂了但是后来忘掉了....最近又重新学了一遍 所谓\(dsu\ on\ tree\)就是处理本文标题:无修改询问子树可合并 ...

  8. poj——2239 Selecting Courses

    poj——2239   Selecting Courses Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10656   A ...

  9. loj6165 一道水题(线性筛)

    题目: https://loj.ac/problem/6165 分析: 最直接的想法就是把1~n的所有数分解质因数,然后每个素数的幂取max 我们首先来看看一共可能有哪些素数? 实际上这些素因数恰好就 ...

  10. 关于用String Calender类 计算闰年的Demo

    package cn.zmh.zuoye; import java.util.Calendar; public class StringRun { public static void main(St ...