Sdoi2017 樹點塗色 lct 線段樹

2022-04-06 19:37:37 字數 1789 閱讀 6499

題意:一棵有根樹,支援x到根染成新顏色,求x到y顏色數,求x子樹裡點到根顏色數最大值

考場發現這個資訊是可減的,但是沒想到lct

特意設計成lct的形式!

如何求顏色數?

維護乙個點和父親的顏色是否一樣,不一樣為1,就是字首和。考慮相鄰的思想和那道「水位線」有點像

x到y的答案就是\(s_x + s_y - 2*s_ + 1\)

乙個點到根染新顏色,對應了lct的access操作,重邊就是一樣輕邊就是不一樣,修改輕重邊就是子樹加,其他兩個操作單點求值,子樹求最大值。用線段樹維護dfs序

#include #include #include #include #include using namespace std;

const int n=1e5+5;

#define fir first

#define sec second

inline int read()

while(c>='0' && c<='9')

return x*f;

}int n, q, op, x, y;

struct edge e[n<<1];

int cnt=1, h[n];

inline void ins(int u, int v) ; h[u]=cnt;

e[++cnt]=(edge); h[v]=cnt;

}int fa[n], deep[n], size[n], mx[n], top[n], dfc, ver[n];

pairdfn[n];

void dfs(int u)

}void dfs(int u, int anc)

inline int lca(int x, int y)

return deep[x] < deep[y] ? x : y;

}namespace seg t[n<<2];

inline void paint(int x, int v)

inline void pushdn(int x)

} inline void merge(int x)

void build(int x, int l, int r)

void add(int x, int l, int r, int ql, int qr, int v)

} int que(int x, int l, int r, int p)

} int que(int x, int l, int r, int ql, int qr)

}#undef lc

#undef rc

}inline void addsub(int u, int val)

inline void quer(int x, int y)

inline void qmax(int x)

namespace lct t[n];

int sz;

inline int wh(int x)

inline int isr(int x)

inline void rotate(int x)

inline void splay(int x)

inline int findr(int x)

void access(int x)

if(y) y=findr(y), addsub(y, -1);

rc=y;

} }void init()

}int main()

}

SDOI2017 樹點塗色 LCT 線段樹

可以發現更新操作就是 text 的 text 操作,這個操作複雜度是 o n log n 的 因此,考慮對於每次的 text 操作,維護每個點到根的路徑上不同的權值個數 每次 text 操作只設計到合併兩個鏈 斷開一條鏈兩種操作,可以通過線段樹維護子樹修改 那麼修改的複雜度就是 o n log 2 ...

SDOI2017 樹點塗色(LCT 線段樹)

給你一棵以 1 為根,有 n 個節點的樹,初始時每個節點的顏色互不相同,記一條路徑的權值為這條路徑 包括起點和終點 上所有不同的顏色個數,一共 m 個操作,每次支援以下 3 種操作之一 把點 x 到根節點的路徑上所有的點染上一種沒有用過的新顏色 求 x 到 y 的路徑的權值 在以 x 為根的子樹中選...

SDOI2017 樹點塗色

description bob有一棵n個點的有根樹,其中1號點是根節點。bob在每個點上塗了顏色,並且每個點上的顏色不同。定義一條路 徑的權值是 這條路徑上的點 包括起點和終點 共有多少種不同的顏色。bob可能會進行這幾種操作 1 x 把點x到根節點的路徑上所有的點染上一種沒有用過的新顏色。2 x ...