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
", 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

原文地址:https://www.cnblogs.com/yousiki/p/6399042.html