您的位置:首页 > 其它

[BZOJ3282][tree][LCT]

2017-03-29 18:53 295 查看

[BZOJ3282][tree][LCT]

题目大意:

给定N个点以及每个点的权值,要你处理接下来的M个操作。操作有4种。操作从0到3编号。点从1到N编号。

0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。

1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接。

2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。

3:后接两个整数(x,y),代表将点X上的权值变成Y。

思路:

LCT裸题???

维护一下子树的xor和就好了。

代码:

#include <bits/stdc++.h>
using namespace std;
const int Maxn = 300005;
inline char get(void) {
static char buf[100000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf, 1, 100000, stdin);
if (p1 == p2) return EOF;
}
return *p1++;
}
inline void read(int &x) {
x = 0; static char c;
for (; !(c >= '0' && c <= '9'); c = get());
for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get());
}

int c[Maxn][2], fa[Maxn], rev[Maxn], s[Maxn], v[Maxn], st[Maxn], top;

inline void pushUp(int x) {
int l = c[x][0], r = c[x][1];
s[x] = s[l] ^ s[r] ^ v[x];
}
inline void pushDown(int x) {
int &l = c[x][0], &r = c[x][1];
if (rev[x]) {
rev[l] ^= 1; rev[r] ^= 1; rev[x] ^= 1;
swap(l, r);
}
}
inline bool Rt(int x) {
return c[fa[x]][0] != x && c[fa[x]][1] != x;
}
inline void rotate(int x) {
int y = fa[x], z = fa[y], l = (c[y][1] == x), r = l ^ 1;
if (!Rt(y)) {
if (c[z][0] == y) c[z][0] = x;
else c[z][1] = x;
}
fa[x] = z; fa[y] = x; fa[c[x][r]] = y;
c[y][l] = c[x][r]; c[x][r] = y;
pushUp(y), pushUp(x);
}

inline void splay(int x) {
st[++top] = x;
for (int i = x; !Rt(i); i = fa[i]) st[++top] = fa[i];
while (top) pushDown(st[top--]);
while (!Rt(x)) {
int y = fa[x], z = fa[y];
if (!Rt(y)) {
if ((c[y][0] == x) ^ (c[z][0] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}

inline void access(int x) {
for (int t = 0; x; t = x, x = fa[x])
splay(x), c[x][1] = t, pushUp(x);
}
inline void makeroot(int x) {
access(x), splay(x), rev[x] ^= 1;
}
inline void link(int x, int y) {
makeroot(x), fa[x] = y;
}
inline void cut(int x, int y) {
makeroot(x); access(y), splay(y);
if (c[y][0] == x) c[y][0] = fa[x] = 0;
}
inline int find(int x) {
access(x), splay(x);
while (c[x][0]) x = c[x][0];
return x;
}
int n, m;
int main(void) {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
read(n), read(m);
for (int i = 1; i <= n; i++) read(s[i]), v[i] = s[i];
int op, x, y;
for (int i = 1; i <= m; i++) {
read(op), read(x), read(y);
if (op == 0) {
makeroot(x), access(y), splay(y);
printf("%d\n", s[y]);
} else if (op == 1) {
if (find(x) != find(y)) link(x, y);
} else if (op == 2) {
if (find(x) == find(y)) cut(x, y);
} else {
access(x); splay(x); v[x]=y; pushUp(x);
}
}
return 0;
}


完。

By g1n0st
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  oi lct