LCT模板题,link和cut是基本操作

更新一条链(u,v)就是做 mroot(u); access(v); splay(v)操作;然后给v打上标记,splay时上下推即可

求一条链(u,v)的最小值,同样做 mroot(u); access(v); splay(v);然后求v的最小值即可

 上述的mroot(u); access(v); splay(v);实际上是提取链(u,v),先将u设为所有辅助树的根节点,然后打通v到根节点的优先链,最后把v旋转到根,v的子树便是链(u,v)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 300005;
int N, Q;
int tot, head[maxn];
struct Edge { int to, next; }edges[maxn<<1];
void init_edges() {
tot = 0;
for (int i = 1; i <= N; i++) head[i] = -1;
}
void addedge(int u, int v) {
edges[tot].to = v; edges[tot].next = head[u]; head[u] = tot++;
}
int fa[maxn], ch[maxn][2], val[maxn], maxv[maxn], tag[maxn], rev[maxn], st[maxn];
void init_tree() {
for (int i = 0; i <= N; i++) {
fa[i] = ch[i][0] = ch[i][1] = val[i] = maxv[i] = tag[i] = rev[i] = 0;
}
}
void dfs(int u) {
for (int i = head[u]; ~i; i = edges[i].next) {
int v = edges[i].to;
if (v == 1 || fa[v]) continue;
fa[v] = u;
dfs(v);
}
}
bool isroot(int x){
return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}
void pushup(int x){
int l = ch[x][0], r = ch[x][1];
maxv[x] = max(max(maxv[l], maxv[r]), val[x]);
}
void pushdown(int x){
int l = ch[x][0], r = ch[x][1];
if (rev[x]) {
if (l) rev[l]^=1;
if (r) rev[r]^=1;
rev[x]^=1;
swap(ch[x][0], ch[x][1]);
}
if (tag[x]) {
if (l) { tag[l]+=tag[x]; maxv[l]+=tag[x], val[l]+=tag[x]; }
if (r) { tag[r]+=tag[x]; maxv[r]+=tag[x], val[r]+=tag[x]; }
tag[x] = 0;
}
}
void rotate(int x){
int y = fa[x], z = fa[y], l, r;
if (ch[y][0] == x) l = 0; else l = 1; r = l^1;
if (!isroot(y)){
if (ch[z][0] == y) ch[z][0] = x; else ch[z][1] = x;
}
fa[x] = z; fa[y] = x; fa[ch[x][r]] = y;
ch[y][l] = ch[x][r]; ch[x][r] = y;
pushup(y); pushup(x);
}
void splay(int x){
int top = 0; st[++top]=x;
for (int i = x; !isroot(i); i = fa[i]) st[++top] = fa[i];
while (top) pushdown(st[top--]);
while (!isroot(x)){
int y = fa[x], z = fa[y];
if (!isroot(y)){
if (ch[y][0] == x^ch[z][0] == y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x){
int t = 0;
while (x) {
splay(x);
ch[x][1] = t;
pushup(x);
x = fa[t = x];
}
}
void mroot(int u){
access(u); splay(u); rev[u] ^= 1;
}
int find(int u) {
access(u); splay(u);
while (ch[u][0]) u = ch[u][0];
return u;
}
bool judge(int u, int v){
return find(u) == find(v);
}
void link(int u, int v){
mroot(u); fa[u] = v;
}
void cut(int u, int v){
mroot(u); access(v); splay(v); fa[ch[v][0]] = 0; ch[v][0] = 0; pushup(v);
}
void update(int u, int v, int w){
mroot(u); access(v); splay(v); tag[v] +=w; maxv[v] += w; val[v] += w;
}
void query(int u,int v){
mroot(u); access(v); splay(v); printf("%d\n", maxv[v]);
}
int main() {
while (~scanf("%d", &N)) {
init_edges();
for (int i = 1; i < N; i++) {
int u, v; scanf("%d%d", &u, &v);
addedge(u, v); addedge(v, u);
}
init_tree();
for (int i = 1; i <= N; i++) {
scanf("%d", &val[i]);
maxv[i] = val[i];
}
dfs(1);
scanf("%d", &Q);
while (Q--) {
int opt, u, v, w;
scanf("%d", &opt);
if (opt == 1){
scanf("%d %d", &u, &v);
if (!judge(u, v)) link(u,v); else puts("-1");
}
if (opt == 2){
scanf("%d %d", &u, &v);
if (judge(u, v) && u != v) cut(u, v); else puts("-1");
}
if (opt == 3){
scanf("%d %d %d", &w, &u, &v);
if (judge(u, v)) update(u, v, w); else puts("-1");
}
if (opt == 4){
scanf("%d %d", &u, &v);
if (judge(u, v)) query(u, v); else puts("-1");
}
}
printf("\n");
}
}