題意:一棵有根樹,支援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 ...