非常妙的一道题。

首先对于操作一“把点x到根节点的路径上所有的点染上一种没有用过的新颜色”,长得是不是有点像LCT中的access操作?进而发现,如果把同一颜色的点连起来作为LCT中的重边的话,那么询问二就相当于问路径上的虚边有多少。

然后第二、三个操作是可以用树剖在线段树上维护的。

设每个点的权值\( val \)为这个点到根的路径上颜色个数,也就是虚边个数。那么考虑access操作的影响,对于他断开的重边,所在子树加一,对于他连上的重边,所在子树减一。直接在access过程中处理即可。

对于操作一,直接access;

对于操作二,\( ans=val[x]+val[y]-2*val[lca(x,y)]+1 \);

对于操作三,用线段树维护区间最大值,直接查询即可。

#include<iostream>
#include<cstdio>
using namespace std;
const int N=300005;
int n,m,h[N],cnt,si[N],fa[N],de[N],hs[N],fr[N],id[N],tmp,rl[N];
struct qwe
{
int ne,to;
}e[N<<1];
struct xianduanshu
{
int l,r,mx,lz;
}q[N<<2];
struct pinghengshu
{
int f,c[2];
}t[N];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(f==-1)
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void add(int u,int v)
{
cnt++;
e[cnt].ne=h[u];
e[cnt].to=v;
h[u]=cnt;
}
void dfs1(int u,int fat)
{
fa[u]=fat;
de[u]=de[fat]+1;
si[u]=1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fat)
{
dfs1(e[i].to,u);
si[u]+=si[e[i].to];
if(si[e[i].to]>si[hs[u]])
hs[u]=e[i].to;
}
}
void dfs2(int u,int top)
{
fr[u]=top;
id[u]=++tmp;
rl[tmp]=u;
if(!hs[u])
return;
dfs2(hs[u],top);
for(int i=h[u];i;i=e[i].ne)
if(e[i].to!=fa[u]&&e[i].to!=hs[u])
dfs2(e[i].to,e[i].to);
}
int lca(int u,int v)
{
for(;fr[u]!=fr[v];de[fr[u]]>de[fr[v]]?u=fa[fr[u]]:v=fa[fr[v]]);//cout<<u<<" "<<v<<" "<<" ";if(de[u]>de[v])cout<<v;else cout<<u;cout<<endl;
return de[u]>de[v]?v:u;
}
void build(int ro,int l,int r)
{
q[ro].l=l,q[ro].r=r;
if(l==r)
{
q[ro].mx=de[rl[l]];
// cout<<rl[l]<<" "<<q[ro].mx<<endl;
return;
}
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
q[ro].mx=max(q[ro<<1].mx,q[ro<<1|1].mx);
}
void pd(int ro)
{
q[ro<<1].mx+=q[ro].lz;
q[ro<<1].lz+=q[ro].lz;
q[ro<<1|1].mx+=q[ro].lz;
q[ro<<1|1].lz+=q[ro].lz;
q[ro].lz=0;
}
void update(int ro,int l,int r,int v)
{//cout<<l<<" "<<r<<" "<<v<<endl;
if(q[ro].l==l&&q[ro].r==r)
{
q[ro].mx+=v;
q[ro].lz+=v;
return;
}
if(q[ro].lz)
pd(ro);
int mid=(q[ro].l+q[ro].r)>>1;
if(r<=mid)
update(ro<<1,l,r,v);
else if(l>mid)
update(ro<<1|1,l,r,v);
else
{
update(ro<<1,l,mid,v);
update(ro<<1|1,mid+1,r,v);
}
q[ro].mx=max(q[ro<<1].mx,q[ro<<1|1].mx);
}
int ques(int ro,int l,int r)
{
if(q[ro].l==l&&q[ro].r==r)
return q[ro].mx;
if(q[ro].lz)
pd(ro);
int mid=(q[ro].l+q[ro].r)>>1;
if(r<=mid)
return ques(ro<<1,l,r);
else if(l>mid)
return ques(ro<<1|1,l,r);
else
return max(ques(ro<<1,l,mid),ques(ro<<1|1,mid+1,r));
}
bool srt(int x)
{
return t[t[x].f].c[0]!=x&&t[t[x].f].c[1]!=x;
}
void zhuan(int x)
{
int l,r,y=t[x].f,z=t[y].f;
if(t[y].c[0]==x)
l=0;
else
l=1;
r=l^1;
if(!srt(y))
{
if(t[z].c[0]==y)
t[z].c[0]=x;
else
t[z].c[1]=x;
}
t[x].f=z;t[y].f=x;
t[t[x].c[r]].f=y;
t[y].c[l]=t[x].c[r];
t[x].c[r]=y;
}
void splay(int x)
{
while(!srt(x))
{
int y=t[x].f,z=t[y].f;
if(!srt(y))
{
if((t[y].c[0]==x)^(t[z].c[0]==y))
zhuan(x);
else
zhuan(y);
}
zhuan(x);
}
}
void acc(int x)
{
for(int i=0;x;i=x,x=t[x].f)
{
splay(x);
if(t[x].c[1])
{
int y=t[x].c[1];
while(t[y].c[0])
y=t[y].c[0];
update(1,id[y],id[y]+si[y]-1,1);
}
t[x].c[1]=i;
if(t[x].c[1])
{
int y=t[x].c[1];
while(t[y].c[0])
y=t[y].c[0];
update(1,id[y],id[y]+si[y]-1,-1);
}
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i=2;i<=n;i++)
t[i].f=fa[i];
while(m--)
{
int o=read();
if(o==1)
{
int x=read();
acc(x);
}
else if(o==2)
{
int x=read(),y=read(),lc=lca(x,y);
printf("%d\n",ques(1,id[x],id[x])+ques(1,id[y],id[y])-2*ques(1,id[lc],id[lc])+1);
// printf("%d %d %d %d\n",ques(1,id[x],id[x]),ques(1,id[y],id[y]),ques(1,id[lc],id[lc]),ques(1,id[fa[lc]],id[fa[lc]]));
}
else
{
int x=read();
printf("%d\n",ques(1,id[x],id[x]+si[x]-1));
}
}
return 0;
}

bzoj 4817: [Sdoi2017]树点涂色【树链剖分+LCT】的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. P3703 [SDOI2017]树点涂色

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

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

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

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

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

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

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

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

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

随机推荐

  1. [Android] 通过GridView仿微信动态添加本地图片

    原文:http://blog.csdn.net/eastmount/article/details/41808179 前面文章讲述的都是"随手拍"中图像处理的操作,此篇文章主要讲述 ...

  2. P2839 畅通工程

    P2839 畅通工程 题目描述 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连, ...

  3. QT程序--CS1.6文件整理及安装器

    这是一个在高二的时候写的一个QT程序,当时对于QT也不算是特别熟悉吧,算是我第一个QT程序,当时由于CS1.6的文件安装的繁琐,又有一些服务器的管理的麻烦操作,对CS的服务器管理一直都很麻烦,当时高二 ...

  4. Atom安装Markdown编辑器

    1.安装插件 2.打开/关闭实时渲染: [Ctrl]+[Shift]+[M] 3.[增强]安装同步滚动插件(markdown-scroll-sync) 4.[增强]安装代码增强插件(language- ...

  5. 202. Segment Tree Query

    最后更新 二刷 09-Jan-17 正儿八经线段树的应用了. 查找区间内的值. 对于某一个Node,有这样的可能: 1)需要查找区间和当前NODE没有覆盖部分,那么直接回去就行了. 2)有覆盖的部分, ...

  6. php.ini中extension默许的地址到底在哪里设置的

    原文: http://www.myexception.cn/php/1436096.html ----------------------------------------------------- ...

  7. CentOS 6.x DRBD

    CentOS 6.x DRBD 一.drbd概述     Distributed Replicated Block Device(DRBD)是一种基于软件的,无共享,复制的存储解决方案,在服务器之间的 ...

  8. 谈谈TensorFlow with CPU support or TensorFlow with GPU support(图文详解)

    不多说,直接上干货! You must choose one of the following types of TensorFlow to install: TensorFlow with CPU ...

  9. iOS7获取UUID以及转换MD5

    近期项目开发,运用到要获取UUID转MD5,可是iOS7不能使用获取的UDID的接口(涉及到隐私),获取MAC地址的方式的接口在iOS7下也废弃了.眼下可能的就是获取UUID了,可是在iOS7下,UU ...

  10. 微信企业号调用js-sdk注意事项

    企业号应用必须添加可信域名,域名必须通过备案,可以是子域名,如果网站带端口,一定也要加上端口号...踩坑记