非常妙的一道题。

首先对于操作一“把点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. MySql数据库导出csv文件命令

    MySql数据库导出csv文件命令: MySql数据库导出csv文件命令: mysql> select first_name,last_name,email from account into ...

  2. 洛谷 P1731 [NOI1999]生日蛋糕

    P1731 [NOI1999]生日蛋糕 题目背景 7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层 生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1<=i<=M ...

  3. windows下开发PHP扩展dll(无需Cygwin)

    windows下开发php扩展网上很多资料都说需要Cygwin,其实完全可以不必安装该东东.没错,是可以在linux下生成骨架后拷到windos下来用,但是,如果没有linux环境呢?什么,装虚拟机? ...

  4. Oracle 10g 升级至10.2.0.4

    http://weihaoluo.blog.163.com/blog/static/224418832010112102355652/   单实例环境 Vmware Server 1.0.6 +Cen ...

  5. ldd

    ldd命令用于判断某个可执行的 binary 档案含有什么动态函式库 [diego@localhost ~/work/branch_dispatch_201511/rtqa_center/source ...

  6. iOS iOS8中 问题&quot;registerForRemoteNotificationTypes: is not supported in iOS 8.0 and later&quot; 解决方式

    问题重述: iOS 8中改变了通知注冊的方式,假设App须要同一时候支持iOS 7 和 8 的话,须要首先检查selector. 解决方式:在Xcode 6中 - (BOOL)application: ...

  7. 浅谈asp.net通过本机cookie仿百度(google)实现搜索input框自己主动弹出搜索提示

    对于通过用户输入关键词实现自己主动弹出相关搜索结果,这里本人给两种解决方式,用于两种不同的情形. 常见方法是在数据库里建一个用户搜索关系表,然后通过用户搜索框输入的keyword异步调用数据表中的相关 ...

  8. vs2013发布网站提示 “未能将文件**复制到**”

    原因:年久失修,原来在项目中的一些文件给删掉或移除了 解决方法:打开.csproj文件(记事本打开),把提示的文件给删除掉.

  9. Linux上ln命令详细说明及软链接和硬链接的区别

    硬链接(hard link) UNIX文件系统提供了一种将不同文件链接至同一个文件的机制,我们称这种机制为链接.它可以使得单个程序对同一文件使用不同的名字.这样的好处是文件系 统只存在一个文件的副本, ...

  10. C项目实践--图书管理系统(1)

    1.功能需求分析 图书管理系统主要用于对大量的图书信息,包括书名.作者.出版社.出版日期.ISBN(书号)等进行增.删.改.查以及保存等操作.同时也包括对用户的管理,用户包括管理员和普通用户两种权限, ...