bob有一棵nn個點的有根樹,其中1號點是根節點。bob在每個點上塗了顏色,並且每個點上的顏色不同。
定義一條路徑的權值是:這條路徑上的點(包括起點和終點)共有多少種不同的顏色。
bob可能會進行這幾種操作:
把點xx到根節點的路徑上所有的點染上一種沒有用過的新顏色。
求xx到yy的路徑的權值。
在以x為根的子樹中選擇乙個點,使得這個點到根節點的路徑權值最大,求最大權值。
bob一共會進行mm次操作
輸入格式:
第一行兩個數n,mn,m。
接下來n-1n−1行,每行兩個數a,ba,b,表示aa與bb之間有一條邊。
接下來mm行,表示操作,格式見題目描述
輸出格式:
每當出現2,3操作,輸出一行。
如果是2操作,輸出乙個數表示路徑的權值
如果是3操作,輸出乙個數表示權值的最大值
輸入樣例#1:
5 61 22 3
3 43 5
2 4 5
3 31 4
2 4 5
1 52 4 5
輸出樣例#1:
3422
共10個測試點
測試點1,1\leq n,m\leq10001≤n,m≤1000
測試點2、3,沒有2操作
測試點4、5,沒有3操作
測試點6,樹的生成方式是,對於i(2\leq i \leq n)i(2≤i≤n),在1到i-1i−1中隨機選乙個點作為i的父節點。
測試點7,1\leq n,m\leq 500001≤n,m≤50000
測試點8,1\leq n \leq 500001≤n≤50000
測試點9,10,無特殊限制
對所有資料,1\leq n \leq 10^51≤n≤105,1\leq m \leq 10^51≤m≤105
時間限制:1s
空間限制:128mb
維護乙個lct,
每個splay
裡都是顏色相同的點
.那麼操作
2的答案就是這兩個點路徑上的虛邊的數量
+1.操作
3的答案就是子樹中每個點到根的路徑虛邊最大值
+1.因為每次操作
1都會用一種新的顏色,那麼
2的答案
=f[x]+f[y]-2*f[lca(x,y)]+1.f[x]代表x
到根的路徑上的虛邊數量
.
然後這個東西顯然樹鏈剖分用線段樹來維護,順便求出
lca.
那麼操作
2為單點查詢,操作
3為區間查詢
(dfn).
然後再考慮操作1對查詢的影響
.
用lct中的
access操作,
每次將一條實邊變成虛邊的時候
,將這顆子樹中的值全部加
1,虛邊變實邊相反
.這裡有乙個細節沒有考慮到
,因為這條路徑是用
splay存的,
那麼原樹上與這條要修改的邊相連的點並不是
splay
中與這條邊相連的那個點
.所以區間修改時要找最淺的那個點,即為
splay
中那顆子樹的最左邊的點
.
1 #include2#define ls o*2
3#define rs o*2+1
4#define pre t[x].fa
5#define ls t[x].ch[0]
6#define rs t[x].ch[1]
7#define maxn 100010
8#define rg register
9using
namespace
std;
10struct
edgee[maxn*2
];13
struct lctt[maxn];
14int head[maxn],edge=0
,top[maxn],dfn[maxn],dfp[maxn],dad[maxn],ed[maxn],deep[maxn],son[maxn],size[maxn];
15int n,b[maxn*4],lazy[maxn*4
];16 inline void add(int
from,int
to)21
void dfs1(int x,int
fa)32}33
int de=0;34
void dfs2(int x,int
fa)43 ed[x]=de;44}
45void build(int o,int l,int
r)47
int mid=(l+r)>>1
;48 build(ls,l,mid);build(rs,mid+1
,r);
49 b[o]=max(b[ls],b[rs]);50}
51 inline void down(int
o)56}57
void change(int o,int l,int r,int u,int v,int
w)61
int mid=(l+r)>>1;62
if(v<=mid) change(ls,l,mid,u,v,w);
63else
if(u>mid) change(rs,mid+1
,r,u,v,w);
64else change(ls,l,mid,u,mid,w),change(rs,mid+1,r,mid+1
,v,w);
65 b[o]=max(b[ls],b[rs]);66}
67 inline bool isrt(int x)
68 inline bool son(int x)
69 inline void rotate(int
x)76 inline void splay(int
x)80 inline void access(int
x)87 rs=y;if
(rs)92}
93}94int find(int o,int l,int r,int
p)101
int query(int o,int l,int r,int u,int
v)110 inline void lca(int x,int
y)116 lca=deep[x]>deep[y]?y:x;
117 printf("
%d\n
",find(1,1,n,dfn[xx])+find(1,1,n,dfn[yy])-2*find(1,1,n,dfn[lca])+1
);118
}119
intmain()
133return0;
134 }
SDOI2017 樹點塗色
description bob有一棵n個點的有根樹,其中1號點是根節點。bob在每個點上塗了顏色,並且每個點上的顏色不同。定義一條路 徑的權值是 這條路徑上的點 包括起點和終點 共有多少種不同的顏色。bob可能會進行這幾種操作 1 x 把點x到根節點的路徑上所有的點染上一種沒有用過的新顏色。2 x ...
SDOI2017 樹點塗色
傳送門 塗色的操作和acc es saccess access 很像啊,如何用lct lctlc t維護這個東西呢。由於每次覆蓋的顏色都不同,且是從當前到結點覆蓋到根節點。那麼如果把顏色相同的一段維護在一條重鏈上,乙個點到根要經過多少虛邊也就包含多少顏色。所以用lct lctlc t模擬覆蓋的過程,...
SDOI2017 樹點塗色
題目鏈結 有三種操作,1.把點 x xx 到根節點的路徑上所有的點染上一種沒有用過的新顏色。2.求 x xx 到 y yy 的路徑的上的不同顏色數。3.在以x xx為根的子樹中選擇乙個點,使得這個點到根節點的路徑的不同顏色數最大,求最大權值。可以發現修改操作的乙個性質 每種顏色的節點一定會形成一條鏈...