bzoj2959
lct+并查集
联赛之后忘了很多东西 复习一下
这并不是一棵树,所以我们不能直接上lct
但是把双联通分量缩了以后就是一棵树了
怎么缩呢 就是把splay拆了合并到一个点上
连通性和双联通分量拿两个并查集维护
access的时候x=find(fa[x])
#include<bits/stdc++.h> using namespace std; const int N = 1.5e5 + 5; struct ufs { int fa[N]; ufs() { for(int i = 1; i < N; ++i) fa[i] = i; } int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } void link(int u, int v) { fa[find(u)] = find(v); } bool con(int u, int v) { return find(u) == find(v); } } a, b; int n, m; int val[N]; queue<int> q; namespace lct { struct node { int rev, sum, w, f; int ch[2]; } t[N]; bool isr(int x) { return !t[x].f || (x != t[t[x].f].ch[0] && x != t[t[x].f].ch[1]); } int wh(int x) { return x == t[t[x].f].ch[1]; } void paint(int x) { t[x].rev ^= 1; swap(t[x].ch[0], t[x].ch[1]); } void upd(int x) { t[x].sum = t[t[x].ch[0]].sum + t[t[x].ch[1]].sum + t[x].w; } void pd(int x) { if(!t[x].rev) return; paint(t[x].ch[0]); paint(t[x].ch[1]); t[x].rev ^= 1; } void rotate(int x) { int y = t[x].f, z = t[y].f, w = wh(x); if(!isr(y)) t[z].ch[wh(y)] = x; t[x].f = z; t[y].ch[w] = t[x].ch[w ^ 1]; t[t[x].ch[w ^ 1]].f = y; t[x].ch[w ^ 1] = y; t[y].f = x; upd(y); upd(x); } void ptd(int x) { if(!isr(x)) ptd(t[x].f); pd(x); } void splay(int x) { ptd(x); for(; !isr(x); rotate(x)) if(!isr(t[x].f)) rotate(wh(x) == wh(t[x].f) ? t[x].f : x); } void access(int x) { for(int p = 0; x; p = x, x = b.find(t[x].f)) { splay(x); t[x].ch[1] = p; t[p].f = x; upd(x); } } void rever(int x) { access(x); splay(x); paint(x); } void expose(int x, int y) { rever(y); access(x); splay(x); } void link(int u, int v) { rever(u); t[u].f = v; } void rebuild(int x, int y) { int rt = x; q.push(x); expose(x, y); while(!q.empty()) { x = q.front(); b.link(x, rt); q.pop(); if(t[x].ch[0]) q.push(t[x].ch[0]); if(t[x].ch[1]) q.push(t[x].ch[1]); t[x].ch[0] = t[x].ch[1] = 0; } t[rt].w = t[rt].sum; } } void link(int u, int v) { u = b.find(u); v = b.find(v); if(u == v) return; if(!a.con(u, v)) lct::link(u, v), a.link(u, v); else lct::rebuild(u, v); } int query(int u, int v) { u = b.find(u); v = b.find(v); if(!a.con(u, v)) return -1; if(u == v) return lct::t[u].w; lct::expose(u, v); return lct::t[u].sum; } void add(int x, int v) { x = b.find(x); lct::t[x].w += v; lct::t[x].sum += v; lct::splay(x); } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) scanf("%d", &lct::t[i].w), val[i] = lct::t[i].sum = lct::t[i].w; while(m--) { int opt, u, v; scanf("%d%d%d", &opt, &u, &v); if(opt == 1) link(u, v); if(opt == 2) add(u, v - val[u]), val[u] = v; if(opt == 3) printf("%d\n", query(u, v)); } return 0; }