LCT板子第11个点一直T
也不是死循环,就是很正经的T
调了一个下午了TAT
#include<bits/stdc++.h>
#define ls(x) son[x][0]
#define rs(x) son[x][1]
using namespace std;
const int MAXN = 1e5 + 5;
int inpt()
{
int x = 0, f = 1;
char ch;
for(ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
if(ch == '-'){
f = -1;
ch = getchar();
}
do{
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar();
}while(ch >= '0' && ch <= '9');
return x * f;
}
int n, m;
int w[MAXN];
int sta[MAXN];
struct LinkCutTree {
struct SplayTree {
int fa[MAXN];
int son[MAXN][2];
int xum[MAXN];//xor_sum
int tag[MAXN];
bool IsRoot(int x) {//x为当前伸展树的根
return son[fa[x]][0] != x && son[fa[x]][1] != x;
}
void Update(int x) {
xum[x] = xum[ls(x)] ^ xum[rs(x)] ^ w[x];
}
void PushDown(int x) {
if(tag[x]) {
swap(ls(x), rs(x));
if(ls(x)) {
tag[ls(x)] ^= tag[x];
}
if(rs(x)) {
tag[rs(x)] ^= tag[x];
}
tag[x] = 0;
}
}
void PushAll(int x) {
if(!IsRoot(x)) {
PushAll(fa[x]);
}
PushDown(x);
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
int c = (son[y][0] != x);//如果x是y的左儿子,则值为0,刚好代表左儿子
son[y][c] = son[x][!c];
fa[son[x][!c]] = y;
fa[x] = z;
if(!IsRoot(y)) {
son[z][son[z][0] != y] = x;
}
son[x][!c] = y;
fa[y] = x;
Update(y);
Update(x);//此顺序必定不能换
}
void Splay(int x) {//将x旋转成根
// PushAll(x);
int t = x, tp = 0;
sta[++tp] = t;
while(!IsRoot(t)) {
t = fa[t];
sta[++tp] = t;
}
while(tp) {
PushDown(sta[tp]);
tp--;
}
while(!IsRoot(x)) {
int y = fa[x], z = fa[y];
int cx = (son[y][0] != x), cy = (son[z][0] != y);
if(IsRoot(y)) {
Rotate(x);
return ;
}
if(cx == cy) {
Rotate(x);
Rotate(x);
}else {
Rotate(y);
Rotate(x);
}
}
}
void Reverse(int x) {
tag[x] ^= 1;
}
}tr;
void Access(int x) {//打通x到根的实链
for(int t = 0; x; t = x, x = tr.fa[x]) {
tr.Splay(x);
tr.son[x][1] = t;
tr.Update(x);
}
}
void MakeRoot(int x) {//使x变成原树的根
Access(x);
tr.Splay(x);
tr.Reverse(x);
}
int FindRoot(int x) {//找出x所在实链的根
Access(x);
tr.Splay(x);
while(tr.son[x][0]) {
x = tr.son[x][0];
}
tr.Splay(x);
return x;
}
void Split(int x, int y) {//分离出x,y之间的路径为一条实链 (以y为根)
MakeRoot(x);
Access(y);
tr.Splay(y);
}
void Link(int x, int y) {//连接x和 y
// if(FindRoot(x) == FindRoot(y)) return ;
MakeRoot(x);
if(FindRoot(y) == x) return ;
tr.fa[x] = y;//建一条虚边
}
void Cut(int x, int y) {//断开x, y
Split(x, y);
if(tr.son[y][0] != x || tr.son[x][1]) return ;
tr.son[y][0] = tr.fa[tr.son[y][0]] = 0;
// tr.Update(y);
}
int Ask(int x, int y) {
Split(x, y);
// tr.Update(y);
return tr.xum[y];
}
void Change(int x, int v) {
tr.Splay(x);
w[x] = v;
// tr.Update(x);
}
}LCT;
int main()
{
freopen("P3690_11.in", "r", stdin);
freopen("My.out", "w", stdout);
n = inpt(), m = inpt();
for(int i = 1; i <= n; i++) {
w[i] = inpt();
}
for(int i = 1; i <= m; i++) {
// cout << i << endl;
int opt = inpt();
int x = inpt(), y = inpt();
if(opt == 0) {
printf("%d\n", LCT.Ask(x, y));
continue;
}
if(opt == 1) {
LCT.Link(x, y);
continue;
}
if(opt == 2) {
LCT.Cut(x, y);
continue;
}
if(opt == 3) {
LCT.Change(x, y);
continue;
}
}
return 0;
}