标签:int 序列 amp ons 代码 == etc 多个 基础
维护链上信息(min,max,sum,xor。。。。。。)
换根
维护子树信息
**
void access(node *x) {
for(node *y = NULL; x; x = (y = x)->fa) //无论实边虚边,x都记录了父亲,所以可以一直跳到根
splay(x), x->ch[1] = y, x->upd(); //把x转上来,虚实变换,然后维护信息
}
void split(node *x, node *y) {
makeroot(x); //让x城成为根
access(y); //打通y到根x的路径,那么现在x->y的路径就在一棵Splay里了
splay(y); //转上y更新信息
}
void link(node *x, node *y) {
makeroot(x); //x成为根
if(findroot(y) != x) x->fa = y; //如果根不是x,说明不在一棵树里,否则直接连虚边
}
void cut(node *x, node *y) {
split(x, y);
if(y->ch[0] == x) y->ch[0] = x->fa = NULL;
}
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL in() {
char ch; int x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 3e5 + 5;
struct LCT {
protected:
struct node {
node *ch[2], *fa;
int val, num, rev;
node(int val = 0, int num = 0, int rev = 0): val(val), num(num), rev(rev) {
ch[0] = ch[1] = fa = NULL;
}
bool ntr() { return fa && (fa->ch[0] == this || fa->ch[1] == this); }
bool isr() { return this == fa->ch[1]; }
void trn() { std::swap(ch[0], ch[1]), rev ^= 1; }
void upd() {
num = val;
if(ch[0]) num ^= ch[0]->num;
if(ch[1]) num ^= ch[1]->num;
}
void dwn() {
if(!rev) return;
if(ch[0]) ch[0]->trn();
if(ch[1]) ch[1]->trn();
rev = 0;
}
};
node s[maxn], *t[maxn];
int top;
void rot(node *x) {
node *y = x->fa, *z = y->fa;
int k = x->isr(); node *w = x->ch[!k];
if(y->ntr()) z->ch[y->isr()] = x;
x->ch[!k] = y, y->ch[k] = w;
y->fa = x, x->fa = z;
if(w) w->fa = y;
y->upd(), x->upd();
}
void splay(node *o) {
t[top = 1] = o;
while(t[top]->ntr()) t[top + 1] = t[top]->fa, top++;
while(top) t[top--]->dwn();
while(o->ntr()) {
if(o->fa->ntr()) rot(o->isr() ^ o->fa->isr()? o : o->fa);
rot(o);
}
}
void access(node *x) {
for(node *y = NULL; x; x = (y = x)->fa)
splay(x), x->ch[1] = y, x->upd();
}
void makeroot(node *x) { access(x), splay(x), x->trn(); }
node *findroot(node *x) {
access(x), splay(x);
while(x->dwn(), x->ch[0]) x = x->ch[0];
return x;
}
void link(node *x, node *y) {
if(findroot(x) == findroot(y)) return;
makeroot(x), x->fa = y;
}
void cut(node *x, node *y) {
makeroot(x), access(y), splay(y);
if(y->ch[0] == x) y->ch[0] = x->fa = NULL;
}
void change(node *x, int y) { splay(x), x->val = y, x->upd(); }
int query(node *x, node *y) {
makeroot(x), access(y), splay(y);
return y->num;
}
public:
void init(int len) { for(int i = 1; i <= len; i++) s[i].val = s[i].num = in(); }
int query(int x, int y) { return query(s + x, s + y); }
void link(int x, int y) { link(s + x, s + y); }
void cut(int x, int y) { cut(s + x, s + y); }
void change(int x, int y) { change(s + x, y); }
}s;
int n, m;
int main() {
n = in(), m = in();
s.init(n);
while(m --> 0) {
int flag = in(), x = in(), y = in();
if(flag == 0) printf("%d\n", s.query(x, y));
if(flag == 1) s.link(x, y);
if(flag == 2) s.cut(x, y);
if(flag == 3) s.change(x, y);
}
return 0;
}
标签:int 序列 amp ons 代码 == etc 多个 基础
原文地址:https://www.cnblogs.com/olinr/p/10525472.html