首页 > 代码库 > BZOJ 3282: Tree

BZOJ 3282: Tree

3282: Tree

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 1714  Solved: 765
[Submit][Status][Discuss]

Description

给定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。

 

Input

第1行两个整数,分别为N和M,代表点数和操作数。

第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。

第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。

 

Output

对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。

Sample Input

3 3
1
2
3
1 1 2
0 1 2
0 1 1

Sample Output

3
1

HINT

 

1<=N,M<=300000

 

Source

动态树

[Submit][Status][Discuss]

 

莫名其妙的红色,LCT模板题

 

#include <bits/stdc++.h>inline int nextChar(void) {  static const int siz = 1 << 20;    static char buffer[siz];  static char *head = buffer + siz;  static char *tail = buffer + siz;    if (head == tail)fread(head = buffer, 1, siz, stdin);  return int(*head++);}inline int nextInt(void) {  register int ret = 0;  register int neg = false;  register int bit = nextChar();  for (; bit < 48; bit = nextChar())    if (bit == ‘-‘)neg ^= true;  for (; bit > 47; bit = nextChar())    ret = ret * 10 + bit - ‘0‘;  return neg ? -ret : ret;}const int mxn = 300005;int n, m, top;int stk[mxn];int val[mxn];int sum[mxn];int fat[mxn];int rev[mxn];int son[mxn][2];inline bool isroot(int t) {  int f = fat[t];  if (!f)return true;  if (son[f][0] == t)return false;  if (son[f][1] == t)return false;  return true;}inline void update(int t) {  sum[t] = val[t];  if (son[t][0])sum[t] ^= sum[son[t][0]];  if (son[t][1])sum[t] ^= sum[son[t][1]];}inline void push(int t) {  rev[t] = 0;  std::swap(son[t][0], son[t][1]);  if (son[t][0])rev[son[t][0]] ^= 1;  if (son[t][1])rev[son[t][1]] ^= 1;}inline void pushdown(int t) {  for (stk[++top] = t; t; )    stk[++top] = t = fat[t];  for (; top; --top)    if (rev[stk[top]])      push(stk[top]);}inline void connect(int t, int f, int k) {  if (t)fat[t] = f;  if (f)son[f][k] = t;}inline void rotate(int t) {  int f = fat[t];  int g = fat[f];  int s = son[f][1] == t;  connect(son[t][!s], f, s);  connect(f, t, !s);  fat[t] = g;  if (g && son[g][0] == f)son[g][0] = t;  if (g && son[g][1] == f)son[g][1] = t;  update(f);  update(t);}inline void splay(int t) {  pushdown(t);  while (!isroot(t)) {    int f = fat[t];    int g = fat[f];    if (isroot(f))      rotate(t);    else {      int a = f && son[f][1] == t;      int b = g && son[g][1] == f;      if (a == b)        rotate(f), rotate(t);      else        rotate(t), rotate(t);    }  }}inline void access(int t) {  for (int p = 0; t; p = t, t = fat[t])    splay(t), son[t][1] = p, update(t);}inline void makeroot(int t) {  access(t), splay(t), rev[t] ^= 1;}inline void cut(int a, int b) {  makeroot(a), access(b), splay(b);  if (son[b][0] == a)son[b][0] = fat[a] = 0;}inline void link(int t, int f) {  makeroot(t), fat[t] = f;}inline int find(int t) {  access(t), splay(t);  while (son[t][0])    t = son[t][0];  return t;}signed main(void) {  n = nextInt();  m = nextInt();  for (int i = 1; i <= n; ++i)    val[i] = sum[i] = nextInt();  for (int i = 1; i <= m; ++i) {    int k = nextInt();    int x = nextInt();    int y = nextInt();    switch (k) {    case 0 :      makeroot(x);      access(y);      splay(y);      printf("%d\n", sum[y]);      break;    case 1:      if (find(x) != find(y))	      link(x, y);      break;    case 2:      if (find(x) == find(y))	      cut(x, y);      break;    case 3:      access(x);      splay(x);      val[x] = y;      update(x);      break;    }  }}

  

@Author: YouSiki

 

BZOJ 3282: Tree