• P3690 【模板】Link Cut Tree (动态树)


    题面

    https://www.luogu.org/problem/P3690

    题解

    #include<cstdio>
    #include<iostream>
    using namespace std;
    
    int f[300050],ch[300050][2];
    int s[300050],v[300050];
    int stk[300050];
    bool r[300050];
    int n,m;
    
    bool opt(int x) {
      return ch[f[x]][1]==x;
    }
    
    bool notroot(int x) {
      return ch[f[x]][0]==x || ch[f[x]][1]==x;
    }
    
    void pushup(int x) {
      s[x]=s[ch[x][0]]^s[ch[x][1]]^v[x];
    }
    
    void pushr(int x) {
      if (!r[x]) return;
      r[x]=false;
      swap(ch[x][0],ch[x][1]); r[ch[x][0]]^=1; r[ch[x][1]]^=1;
    }
    
    void rotate(int x) {
      int y=f[x],z=f[y],s=opt(x);
      if (notroot(y)) ch[z][opt(y)]=x; f[x]=z;
      ch[y][s]=ch[x][1^s]; if (ch[x][1^s]) f[ch[x][1^s]]=y;
      ch[x][1^s]=y; f[y]=x;
      pushup(y); pushup(x);
    }
    
    void splay(int x) {
      int y=x,t=0;
      while(notroot(y)) stk[t++]=y,y=f[y];
      stk[t]=y;
      while (t>=0) pushr(stk[t]),t--;
      while (notroot(x)) {
        if (!notroot(f[x])) rotate(x);
        else {
          if (opt(x)==opt(f[x]) && notroot(f[x])) rotate(f[x]),rotate(x);
          else rotate(x),rotate(x);
        }
      }
    }
    
    void access(int x) {
      int y=0;
      while (x) {
        splay(x);
        ch[x][1]=y;pushup(x);
        y=x;x=f[x];
      }
    }
    
    void makeroot(int x) {
      access(x); splay(x);
      r[x]^=1;
      pushr(x);
    }
    
    int findroot(int x) {
      access(x); splay(x);
      while (ch[x][0]) pushr(x),x=ch[x][0];
      return x;
    }
    
    void split(int x,int y) {
      makeroot(x);
      access(y); splay(y);
    }
    
    void link(int x,int y) {
      makeroot(x);
      if (findroot(y)!=x) f[x]=y;
    }
    
    void cut(int x,int y) {
      makeroot(x);
      if (findroot(y)==x && f[x]==y && !ch[x][1]) {
        f[x]=ch[y][0]=0;
        pushup(y);
      }
    }
    
    int main(){
      int i,op,x,y;
      scanf("%d %d",&n,&m);
      for (i=1;i<=n;i++) scanf("%d",&v[i]);
      for (i=1;i<=m;i++) {
        scanf("%d %d %d",&op,&x,&y);
        if (op==0) split(x,y),pushup(y),printf("%d
    ",s[y]); 
        else if (op==1) link(x,y);
        else if (op==2) cut(x,y);
        else splay(x),v[x]=y;
      }
      return 0;
    }
  • 相关阅读:
    clear:both其实是有瑕疵的
    CSS3不遥远,几个特性你要知道
    JavaScript使用数组拼接字符串性能如何?
    CSS网页宽度怎么定比较合适
    浅析JavaScript的垃圾回收机制
    淡入淡出效果的js原生实现
    非阻塞式JavaScript脚本及延伸知识
    HTML5 Canvas圣诞树
    Ubuntu查看和自动挂载硬盘
    正则表达式批量重命名
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11427329.html
Copyright © 2020-2023  润新知