题目大意:维护一种动态树形数据结构,支持:
1.求树上两点之间的点的异或和。
2.连接两点(不保证不连通)
3.删除连点之间的边(不保证两点联通)
4.将一个点的点权改成一个值
思路:还是LCT,思路也比较裸。主要是它各种不保证,所以要多加判断。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 300010
using namespace std;
struct Complex{
int val,_xor;
bool reverse;
Complex *son[2],*father;
Complex(int _val);
void Reverse() {
reverse ^= 1;
swap(son[0],son[1]);
}
bool Check() {
return father->son[1] == this;
}
void PushDown();
void PushUp();
}*tree[MAX],*nil = new Complex(0);
Complex:: Complex(int _val) {
val = _xor = _val;
reverse = false;
son[0] = son[1] = father = nil;
}
void Complex:: PushDown() {
if(reverse) {
son[0]->Reverse();
son[1]->Reverse();
reverse = false;
}
}
void Complex:: PushUp() {
_xor = son[0]->_xor ^ son[1]->_xor ^ val;
}
int points,asks;
int src[MAX];
inline void Rotate(Complex *a,bool dir);
inline void Splay(Complex *a);
inline void PushPath(Complex *a);
inline void Access(Complex *a);
inline void ToRoot(Complex *a);
inline void Link(Complex *x,Complex *y);
inline void Cut(Complex *x,Complex *y);
inline void Modify(Complex *a,int c);
inline int Ask(Complex *x,Complex *y);
inline Complex *FindRoot(Complex *x);
int main()
{
cin >> points >> asks;
for(int x,i = 1;i <= points; ++i)
scanf("%d",&x),tree[i] = new Complex(x);
for(int flag,x,y,i = 1;i <= asks; ++i) {
scanf("%d%d%d",&flag,&x,&y);
if(!flag) printf("%d\n",Ask(tree[x],tree[y]));
else if(flag == 1) Link(tree[x],tree[y]);
else if(flag == 2) Cut(tree[x],tree[y]);
else Modify(tree[x],y);
}
return 0;
}
inline void Rotate(Complex *a,bool dir)
{
Complex *f = a->father;
f->son[!dir] = a->son[dir];
f->son[!dir]->father = f;
a->son[dir] = f;
a->father = f->father;
if(f->father->son[0] == f || f->father->son[1] == f)
f->father->son[f->Check()] = a;
f->father = a;
f->PushUp();
}
inline void Splay(Complex *a)
{
PushPath(a);
while(a == a->father->son[0] || a == a->father->son[1]) {
Complex *p = a->father->father;
if(p->son[0] != a->father && p->son[1] != a->father)
Rotate(a,!a->Check());
else if(!a->father->Check()) {
if(!a->Check())
Rotate(a->father,true),Rotate(a,true);
else Rotate(a,false),Rotate(a,true);
}
else {
if(a->Check())
Rotate(a->father,false),Rotate(a,false);
else Rotate(a,true),Rotate(a,false);
}
}
a->PushUp();
}
inline void PushPath(Complex *a)
{
static Complex *stack[MAX];
int top = 0;
for(;a->father->son[0] == a || a->father->son[1] == a;a = a->father)
stack[++top] = a;
stack[++top] = a;
while(top)
stack[top--]->PushDown();
}
inline void Access(Complex *a)
{
Complex *last = nil;
while(a != nil) {
Splay(a);
a->son[1] = last;
a->PushUp();
last = a;
a = a->father;
}
}
inline void ToRoot(Complex *a)
{
Access(a);
Splay(a);
a->Reverse();
}
inline void Link(Complex *x,Complex *y)
{
if(FindRoot(x) == FindRoot(y)) return ;
ToRoot(x);
x->father = y;
}
inline void Cut(Complex *x,Complex *y)
{
if(x == y || FindRoot(x) != FindRoot(y)) return ;
ToRoot(x);
Access(y);
Splay(y);
if(y->son[0] != x) return ;
y->son[0] = nil;
x->father = nil;
y->PushUp();
}
inline Complex *FindRoot(Complex *a)
{
while(a->father != nil)
a = a->father;
return a;
}
inline void Modify(Complex *a,int c)
{
Splay(a);
a->val = c;
a->PushUp();
}
inline int Ask(Complex *x,Complex *y)
{
ToRoot(x);
Access(y);
Splay(y);
return y->_xor;
}
本文详细介绍了如何维护一种动态树形数据结构,包括求两点间点的异或和、连接两点、删除边及修改点权等操作。采用LCT(Lazy Propagation Tree)实现,适用于不保证连通性的情况。
2752

被折叠的 条评论
为什么被折叠?



