题目链接

考试考了一道类似的题目,然后不争气的挂掉了,于是跑过来学习这道题的解法...

我还是太菜了....

我们可以发现任意时刻,原树中颜色相同的点的集合一定是一条链,

即上面这种状态,而这种结构是不是跟某种毒瘤数据结构很想,没错,就是LCT

我们发现LCT中的每一颗splay对应着每一段颜色的链

修改节点x到根的颜色时,只需要access一下就好了

我们再考虑每一次修改时对答案的影响

每一个节点到根的权值记作f[i],显然f[i]就是i节点到根节点所经过的轻边数目加1

我们再利用一颗线段树维护dfs序上的f[]数组,方便查询

我们access是每次将虚边变为实边是就将那颗子树中的f[]数组减一

每次实边边虚边就加一

操作三的答案可以通过dfs序查询子树最大

而操作二的答案可很容易发现就是f[x]+f[y]-2*f[lca(x,y)]+1

一样维护一下就好了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue> using namespace std; const int mn = 1e5 + ;
const int inf = 0x3f3f3f3f; struct edge{int to,next;};
edge e[mn*];
int head[mn],edge_max,n,m;
int mx[mn*],tag[mn*];
int fa[mn],in[mn],out[mn],deep[mn],id[mn],clo,siz[mn],bl[mn]; void add(int x,int y)
{
e[++edge_max].to=y;
e[edge_max].next=head[x];
head[x]=edge_max;
} void dfs(int x)
{
siz[x]=;
in[x]=++clo;
id[clo]=x;
for(int i=head[x]; i; i=e[i].next)
{
if(e[i].to==fa[x]) continue;
fa[e[i].to]=x;
deep[e[i].to]=deep[x]+;
dfs(e[i].to);
siz[x]+=siz[e[i].to];
}
out[x]=clo;
} void dfs2(int x,int chain)
{
bl[x]=chain;
int k=;
for(int i=head[x]; i; i=e[i].next)
{
if(e[i].to!=fa[x] && siz[e[i].to]>siz[k])
k=e[i].to;
}
if(!k) return ;
dfs2(k,chain);
for(int i=head[x]; i; i=e[i].next)
{
if(e[i].to!=fa[x] && e[i].to!=k)
dfs2(e[i].to,e[i].to);
}
} int lca(int x,int y)
{
while(bl[x]!=bl[y])
{
if(deep[bl[x]]<deep[bl[y]]) swap(x,y);
x = fa[bl[x]];
}
if(deep[x]>deep[y]) swap(x,y);
return x;
} void updown(int cur)
{
mx[cur]=max(mx[cur<<],mx[cur<<|]);
} void pushdown(int cur)
{
if(tag[cur])
{
tag[cur<<]+=tag[cur];
tag[cur<<|]+=tag[cur];
mx[cur<<]+=tag[cur];
mx[cur<<|]+=tag[cur];
tag[cur]=;
}
}
void modify(int l,int r,int cur,int L,int R,int z)
{
if(l>=L && r<=R)
{
tag[cur]+=z;
mx[cur]+=z;
return ;
}
if(l>R || r<L) return ;
int mid=l+r>>;
pushdown(cur);
modify(l,mid,cur<<,L,R,z);
modify(mid+,r,cur<<|,L,R,z);
updown(cur);
}
int query(int l,int r,int cur,int L,int R)
{
if(l>=L && r<=R) return mx[cur];
if(l>R || r<L) return -inf;
int mid=l+r>>;
pushdown(cur);
int ans;
ans=max(query(l,mid,cur<<,L,R),query(mid+,r,cur<<|,L,R));
updown(cur);
return ans;
}
void build(int l,int r,int cur)
{
if(l==r)
{
mx[cur]=deep[id[l]];
return ;
}
int mid=l+r>>;
build(l,mid,cur<<);
build(mid+,r,cur<<|);
updown(cur);
}
struct LCT
{
int fa[mn],c[mn][];
bool nroot(int x)
{
return c[fa[x]][]==x || c[fa[x]][] ==x;
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int flag;
if(c[y][]==x) flag=;
else flag=;
if(nroot(y))
{
if(c[z][]==y) c[z][]=x;
else c[z][]=x;
}
c[y][flag^]=c[x][flag];fa[c[y][flag^]]=y;
c[x][flag]=y;
fa[y]=x,fa[x]=z;
}
void splay(int x)
{
while(nroot(x))
{
int y=fa[x],z=fa[y];
if(nroot(y))
{
if((c[z][]==y) ^ (c[y][]==x)) rotate(x);
rotate(y);
}
rotate(x);
}
}
int findroot(int x)
{
while(c[x][]) {
x=c[x][];
} return x;
}
void access(int x)
{
int y=;
while(x)
{
splay(x);
if(c[x][])
{
int tmp=findroot(c[x][]);
modify(,n,,in[tmp],out[tmp],);
}
if(y)
{
int tmp=findroot(y);
modify(,n,,in[tmp],out[tmp],-);
}
c[x][]=y;
y=x;
x=fa[x];
}
}
}T; int main()
{
int opt,x,y,m;
scanf("%d%d",&n,&m);
for(int i=; i<n; i++)
{
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
deep[]=;
dfs();
dfs2(,);
build(,n,);
for(int i=;i<=n;i++)
T.fa[i]=fa[i];
for(int i=; i<=m; i++)
{
scanf("%d%d",&opt,&x);
if(opt==)
T.access(x);
else if(opt==)
{
scanf("%d",&y);
int ans=;
ans=query(,n,,in[x],in[x]);
ans+=query(,n,,in[y],in[y]);
int z=lca(x,y);
ans-=*query(,n,,in[z],in[z]);
ans++;
printf("%d\n",ans);
}
else printf("%d\n",query(,n,,in[x],out[x]));
}
return ;
}

BZOJ 4817数点涂色题解的更多相关文章

  1. [BZOJ 1260][CQOI2007]涂色paint 题解(区间DP)

    [BZOJ 1260][CQOI2007]涂色paint Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为 ...

  2. 【DP】BZOJ 1260: [CQOI2007]涂色paint

    1260: [CQOI2007]涂色paint Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 893  Solved: 540[Submit][Stat ...

  3. BZOJ 1260 [CQOI2007]涂色paint(区间DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1260 [题目大意] 假设你有一条长度为n的木版,初始时没有涂过任何颜色 每次你可以把一 ...

  4. BZOJ 1260: [CQOI2007]涂色paint( 区间dp )

    区间dp.. dp( l , r ) 表示让 [ l , r ] 这个区间都变成目标颜色的最少涂色次数. 考虑转移 : l == r 则 dp( l , r ) = 1 ( 显然 ) s[ l ] = ...

  5. BZOJ 1260: [CQOI2007]涂色paint【区间DP】

    Description 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符串表示这个目标:RGBGR. 每次你可以把一段连续 ...

  6. 【算法•日更•第三十期】区间动态规划:洛谷P4170 [CQOI2007]涂色题解

    废话不多说,直接上题:  P4170 [CQOI2007]涂色 题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符 ...

  7. bzoj 1260涂色 题解

    题面 区间dp, 我学的也不怎么好. myj说动态规划就是搜索的无限剪枝. 所以是搜了网上的代码, 看了看. 思路就是枚举区间,f数组就是存储从i到j需要的最少次数, 当然一开始他们的值要先设置一个很 ...

  8. BZOJ 1260 CQOI2007 涂色paint 动态规划

    题目大意:给定一块木板,上面每一个位置有一个颜色,问最少刷几次能达到这个颜色序列 动态规划,能够先去重处理(事实上不是必需),令f[i][j]代表将i開始的j个位置刷成对应颜色序列的最小次数.然后状态 ...

  9. 洛谷P4170 [CQOI2007]涂色题解

    废话: 这个题我第一眼看就是贪心呐, 可能是我之前那做过一道类似的题这俩题都是关于染色的 现在由于我帅气无比的学长的指导, 我已经豁然开朗, 这题贪心不对啊, 当时感觉自己好厉害贪心都能想出来 差点就 ...

随机推荐

  1. Python2 Python3 urllib方法对应

    Python2 name Python3 nameurllib.urlopen() urllib.request.urlopen()urllib2.urlopen() urllib.request.u ...

  2. 前端页面布局之Grid布局

    在讲布局前,先说两句题外话,写博时,突然想到了郭德纲说过的一个段子“说两个人骂架,不是你有理,你嗓门大,你唾沫星子崩我一脸,你就能骂赢,要看谁命长,过两年你死了,我站你坟头咋说咋是对的,你在那小匣里还 ...

  3. SVN 提交时文件锁定 svn: E155004: '' is already locked

    1.先安装TortoiseSVN TortoiseSVN安装成功后,找到工作路径下的项目右键 TortoiseSVN --> Clean up... --> Break locks 勾选上 ...

  4. scikit-learn的基本使用

    在机器学习和数据挖掘的应用中,scikit-learn是一个功能强大的python包.在数据量不是过大的情况下,可以解决大部分问题.学习使用scikit-learn的过程中,我自己也在补充着机器学习和 ...

  5. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  6. 【python之路36】进程、线程、协程相关

    线程详细用法请参考:http://www.cnblogs.com/sunshuhai/articles/6618894.html 一.初始多线程 通过下面两个例子的运行效率,可以得知多线程的速度比单线 ...

  7. 容斥原理学习(Hdu 4135,Hdu 1796)

    题目链接Hdu4135 Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  8. Zigbee安全入门(一)—— 技术介绍和安全策略

    么是Zigbee? Zigbee说白了就是类似wifi.蓝牙的一种交换数据的方式,学术点说就是低成本.用于低功耗嵌入式设备(无线电系统),用以促进机器与机器之间高效且有效通信(通常相距10-100米) ...

  9. WPF 单个模块换肤

    xmal: <Window x:Class="wpfSkin.MainWindow" xmlns="http://schemas.microsoft.com/win ...

  10. io.spring.platform继承方式和import方式更改依赖版本号的问题

    使用io.spring.platform时,它会管理各类经过集成测试的依赖版本号. 但有的时候,我们想使用指定的版本号,这个时候就需要去覆盖io.spring.platform的版本号. 前面的文章总 ...