Description

Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路
径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
1 x:
把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
2 x y:
求x到y的路径的权值。
3 x y:
在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
Bob一共会进行m次操作
 

Input

第一行两个数n,m。
接下来n-1行,每行两个数a,b,表示a与b之间有一条边。
接下来m行,表示操作,格式见题目描述
1<=n,m<=100000
 

Output

每当出现2,3操作,输出一行。
如果是2操作,输出一个数表示路径的权值
如果是3操作,输出一个数表示权值的最大值
 

Sample Input

5 6
1 2
2 3
3 4
3 5
2 4 5
3 3
1 4
2 4 5
1 5
2 4 5

Sample Output

3
4
2
2

        --by BZOJ

http://www.lydsy.com/JudgeOnline/problem.php?id=4817



大概自己也没想到会回来写这道题吧。

一直对之前见到的,没做出来的题挺抵触的,

不过这是不对的,

题做不出来,也正常,

谁还能把所有的题全做出来呢,

况且,我见到这个题时还不会LCT,

我当时已经打出了树链剖分做法的全部了,

当然爆了一两个点的栈,SD的省选嘛,

然而自己弱是不应该找理由的,

题做不出来就是弱,

没理由的,

那就不应该逃避了,

那么,如果我没有死,你们都将看到我;



如果用LCT记录颜色个数的话,会非常僵,大概只能解决树链剖分解决的问题,

也就是操作三之外的;

但在观察每一个时期树上的颜色情况,发现与LCT的结构类似;

于是考虑利用LCT的结构维护颜色;

对于一二操作;

一就是从某点ACCESS;

二就是从某点空跑ACCESS而不改变splay的组成;

考虑一对三的影响:

发现在ACCESS连接两个点时,父方的点的原儿子的子树到根的颜色数+1,儿子方的点自己的子树颜色树减一;

维护线段树即可;

代码:

 #include<cstdio>
using namespace std;
int max[],mark[],rank[],dep[],size[],a[];
struct dt{
int fa,ch[];
}data[];
struct ss{
int to,next;
}e[];
int first[],num;
int n,m;
void build(int ,int );
void dfs(int ,int ,int );
void builine(int ,int ,int );
void access(int );
int find_top(int );
void splay(int );
void roll(int );
void find(int ,int );
void add(int ,int ,int ,int ,int ,int );
int ans(int ,int ,int ,int ,int );
void down(int );
inline void in(int &ans)
{
ans=;bool p=false;char ch=getchar();
while((ch>'' || ch<'')&&ch!='-') ch=getchar();
if(ch=='-') p=true,ch=getchar();
while(ch<=''&&ch>='') ans=ans*+ch-'',ch=getchar();
if(p) ans=-ans;
}
int main()
{
int i,j,k,x,y;
in(n),in(m);
for(i=;i<=n-;i++){
in(j),in(k);
build(j,k);build(k,j);
}
num=;dfs(,,);
num=;builine(,n,);
for(i=;i<=m;i++){
in(j);
if(j==){
in(x);
access(x);
}
if(j==){
in(x),in(y);
find(x,y);
}
if(j==){
in(x);
y=ans(,n,,rank[x],rank[x]+size[x]-);
printf("%d\n",y);
}
}
return ;
}
void build(int f,int t){
e[++num].next=first[f];
e[num].to=t;
first[f]=num;
}
void dfs(int now,int d,int fa){
int i;
dep[now]=d;size[now]=;rank[now]=++num;a[num]=now;data[now].fa=fa;
for(i=first[now];i;i=e[i].next)
if(e[i].to!=fa){
dfs(e[i].to,d+,now);
size[now]+=size[e[i].to];
}
}
void builine(int l,int r,int nu){
if(l==r){
max[nu]=dep[a[++num]];
return ;
}
int mid=(l+r)>>;
builine(l,mid,nu<<);
builine(mid+,r,nu<<|);
max[nu]=max[nu<<]>max[nu<<|]?max[nu<<]:max[nu<<|];
}
void access(int x){
int y=,z;
while(x){
splay(x);z=find_top(y);
if(z)add(,n,,rank[z],rank[z]+size[z]-,-);
z=data[x].ch[];
data[x].ch[]=y;
y=x;x=data[x].fa;
z=find_top(z);
if(z)add(,n,,rank[z],rank[z]+size[z]-,);
}
}
int find_top(int x){
splay(x);
while(data[x].ch[])
x=data[x].ch[];
return x;
}
void splay(int x){
if(!x)return ;
int fa,fafa;
fa=data[x].fa;fafa=data[fa].fa;
for(;data[fa].ch[]==x||data[fa].ch[]==x;roll(x),fa=data[x].fa,fafa=data[fa].fa){
if(data[fafa].ch[]==fa||data[fafa].ch[]==fa){
if((data[fafa].ch[]==fa)^(data[fa].ch[]==x))
roll(x);
else
roll(fa);
}
}
}
void roll(int now){
int fa=data[now].fa,fafa=data[fa].fa,wh=data[fa].ch[]==now;
data[fa].ch[wh]=data[now].ch[wh^];data[data[fa].ch[wh]].fa=fa;
data[now].ch[wh^]=fa;data[fa].fa=now;
data[now].fa=fafa;
if (data[fafa].ch[]==fa||data[fafa].ch[]==fa)
data[fafa].ch[data[fafa].ch[]==fa]=now;
}
void find(int x,int y){
int ans=;
x=find_top(x);y=find_top(y);
while(x!=y){
if(dep[x]>dep[y]){
splay(x);x=find_top(data[x].fa);ans++;
}
else{
splay(y);y=find_top(data[y].fa);ans++;
}
}
printf("%d\n",ans);
}
void add(int l,int r,int nu,int L,int R,int x){
if(L<=l&&r<=R){
max[nu]+=x;
mark[nu]+=x;
return ;
}
int mid=(l+r)>>;
down(nu);
if(L<=mid)
add(l,mid,nu<<,L,R,x);
if(R>mid)
add(mid+,r,nu<<|,L,R,x);
max[nu]=max[nu<<]>max[nu<<|]?max[nu<<]:max[nu<<|];
}
int ans(int l,int r,int nu,int L,int R){
if(L<=l&&r<=R)
return max[nu];
int mid=(l+r)>>,lm=,rm=;
down(nu);
if(L<=mid)
lm=ans(l,mid,nu<<,L,R);
if(R>mid)
rm=ans(mid+,r,nu<<|,L,R);
if(lm>rm)return lm;
return rm;
}
void down(int nu){
if(!mark[nu])return;
max[nu<<]+=mark[nu];max[nu<<|]+=mark[nu];
mark[nu<<]+=mark[nu];mark[nu<<|]+=mark[nu];
mark[nu]=;
}

SDOI2017 树点涂色——LCT the END的更多相关文章

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

    [Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成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+线段树

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

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

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

  5. BZOJ4817[Sdoi2017]树点涂色——LCT+线段树

    题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...

  6. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

  7. BZOJ 4817: [Sdoi2017]树点涂色 LCT+Access的性质+DFS序+线段树

    Code: #include<bits/stdc++.h> #define maxn 200003 #define inf -1000000 using namespace std; vo ...

  8. BZOJ.4817.[SDOI2017]树点涂色(LCT DFS序 线段树)

    题目链接 操作\(1.2\)裸树剖,但是操作\(3\)每个点的答案\(val\)很不好维护.. 如果我们把同种颜色的点划分到同一连通块中,那么向根染色的过程就是Access()! 最初所有点间都是虚边 ...

  9. 【bzoj4817】[Sdoi2017]树点涂色 LCT+LCA+线段树

    题目描述 给出一棵n个点,以1为根的有根树,每个点初始染有互不相同的颜色.定义一条路径的权值为路径上的颜色种类数.现有m次操作,每次操作为以下三种之一: 1 x: 把点x到根节点的路径上所有的点染上一 ...

随机推荐

  1. delphi 10.2---非常简单的数组用法求和

    unit Unit9; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  2. day5:python学习之集合

    0. 集合的作用及特点 集合具有去重和关系测试两大作用,它具有无序的特点. list1 = [1,2,3,4,5,7,6,8,6,4] list1 = set(list1) print(list1) ...

  3. BurpSuite系列----Extender模块(扩展器)

    一.简介 Burp在软件中提供了支持第三方拓展插件的功能,方便使用者编写自己的自定义插件或从插件商店中安装拓展插件.Burp扩展程序可以以多种方式支持自定义Burp的行为,例如:修改HTTP请求和响应 ...

  4. 通过MSI解压缩Cab文件

    迁移自我的Github 如果只是想做类似解压缩的操作,那么可以使用如下命令行 C:\Windows\System32\expand.exe <cab file path> -F:* < ...

  5. [转] Ansible 内置变量参考

    Quick reference for Ansible variables [From] https://github.com/lorin/ansible-quickref

  6. hdu 3709 Balanced Number(平衡数)--数位dp

    Balanced Number Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) ...

  7. [Xamarin.Android]如何引用JAR檔案 (转帖)

    這個範例是如何在Xamarin.Android中去使用一個我們自行在開發的JAR檔案. 主要會執行的步驟如下 1. 在Xamarin建立一個Android Java Bindings Library ...

  8. (转)linux运维必会MySQL企业面试题

    linux运维必会MySQL企业面试题  老男孩教育运维班全体学员MySQL必会企业面试题最实战.最细致.最落地的运维实训基地,老男孩教育连续多年国内平均就业工资最高! 数据库的重要性是所有技术里最核 ...

  9. Windows Server 2003、2008、2012系统的安装

    说在前面的话 Windows Server 2003,和Windows XP十分相似,可以简单地认为Windows Server 2003是在Windows XP的基础上多了一些服务器管理和操作的功能 ...

  10. python笔记03-----文件操作

    文件操作 创建一个文件名字为filename 内容是 BJSHGDTW 打印文件编码 f = open("filename",'r',encoding="utf-8&qu ...