zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    鼠标事件
    表单事件
    打印20行10列的星形矩形
    打印nn乘法表
    小芳的妈妈每天给她2.5元钱,她都会存起来,但是,每当这一天是存钱的第5天或者5的倍数的话,她都会花去6元钱,请问,经过多少天,小芳才可以存到100元钱。
    我国最高山峰是珠穆朗玛峰:8848m,我现在有一张足够大的纸张,厚度为:0.01m。请问,我折叠多少次,就可以保证厚度不低于珠穆朗玛峰的高度?
    匿名函数
    冒泡排序
    session --中间件
    对cookie-parser的理解(签名、加密)
  • 原文地址:https://www.cnblogs.com/yousiki/p/6399042.html
Copyright © 2011-2022 走看看