SDOI2017 樹點塗色

2022-05-08 04:15:12 字數 3503 閱讀 4560

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 6

1 22 3

3 43 5

2 4 5

3 31 4

2 4 5

1 52 4 5

輸出樣例#1:

342

2

共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≤10​5​​,1\leq m \leq 10^51≤m≤10​5​​

時間限制: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為根的子樹中選擇乙個點,使得這個點到根節點的路徑的不同顏色數最大,求最大權值。可以發現修改操作的乙個性質 每種顏色的節點一定會形成一條鏈...