• [SDOI2017]树点涂色


    Problem

    三种操作

    • 1 x
      把点x到根节点的路径上所有的点染上一种没有用过的新颜色。

    • 2 x y
      求x到y的路径的权值。

    • 3 x
      在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

    显然挺板子的(LCT)啊 求个(LCA)套个线段树写一写。。
    这里求(LCA)用了树剖?鬼知道为什么我用了树剖。。

    // Isaunoya
    #include<bits/stdc++.h>
    using namespace std ;
    using LL = long long ;
    using uint = unsigned int ;
    #define int long long
    #define fir first
    #define sec second
    #define pb push_back
    #define mp(x , y) make_pair(x , y)
    template < typename T > inline void read(T & x) { x = 0 ; int f = 1 ; register char c = getchar() ;
      for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
      for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
      x *= f ;
    }
    template < typename T > inline void print(T x) {
      if(! x) { putchar('0') ; return ; }
      static int st[105] ;
      if(x < 0) putchar('-') , x = -x ;
      int tp = 0 ;
      while(x) st[++ tp] = x % 10 , x /= 10 ;
      while(tp) putchar(st[tp --] + '0') ;
    }
    template < typename T > inline void print(T x , char c) { print(x) ; putchar(c) ; }
    template < typename T , typename ...Args > inline void read(T & x , Args & ...args) { read(x) ; read(args...) ; }
    template < typename T > inline void sort( vector < T > & v) { sort(v.begin() , v.end()) ; return ; }
    template < typename T > inline void unique( vector < T > & v) { sort(v) ; v.erase(unique(v.begin() , v.end()) , v.end()) ; }
    template < typename T > inline void cmax(T & x , T y) { if(x < y) x = y ; return ; }
    template < typename T > inline void cmin(T & x , T y) { if(x > y) x = y ; return ; }
    const int Mod = LLONG_MAX ;
    inline int QP(int x , int y) { int ans = 1 ;
      for( ; y ; y >>= 1 , x = (x * x) % Mod)
        if(y & 1) ans = (ans * x) % Mod ;
      return ans ;
    }
    template < typename T > inline T gcd(T x , T y) { if(y == 0) return x ; return gcd(y , x % y) ; }
    template < typename T > inline T lcm(T x , T y) { return x * y / gcd(x , y) ; }
    template < typename T > inline void mul(T & x , T y) { x = 1LL * x * y ; if(x >= Mod) x %= Mod ; }
    template < typename T > inline void add(T & x , T y) { if((x += y) >= Mod) x -= Mod ; }
    template < typename T > inline void sub(T & x , T y) { if((x -= y) < 0) x += Mod ; }
    int n , m ;
    const int N = 1e5 + 5 ;
    int d[N] , rev[N] ; int tot = 0 ;
    int L[N << 2] , R[N << 2] ;
    int tag[N << 2] ; int mx[N << 2] ;
    inline void pushdown(int x) { if(! tag[x]) return ;
      tag[x << 1] += tag[x] ; tag[x << 1 | 1] += tag[x] ;
      mx[x << 1] += tag[x] ; mx[x << 1 | 1] += tag[x] ; tag[x] = 0 ;
    }
    inline void build(int  l , int r , int rt) { if(l == r) { mx[rt] = d[rev[l]] ; return ; } int mid = l + r >> 1 ;
      build(l , mid , rt << 1) ; build(mid + 1 , r , rt << 1 | 1) ; mx[rt] = max(mx[rt << 1] , mx[rt << 1 | 1]) ;
    }
    inline void update(int a , int b , int l , int r , int rt , int val) {
      if(a <= l && r <= b) { tag[rt] += val ; mx[rt] += val ; return ; }
      pushdown(rt) ; int mid = l + r >> 1 ;
      if(a <= mid) update(a , b , l , mid , rt << 1 , val) ;
      if(b > mid) update(a , b , mid + 1 , r , rt << 1 | 1 , val) ;
      mx[rt] = max(mx[rt << 1] , mx[rt << 1 | 1]) ;
    }
    inline int query(int a , int b , int l , int r , int rt) {
      if(a <= l && r <= b) return mx[rt] ; pushdown(rt) ;
      int mid = l + r >> 1  ; int ans = 0 ;
      if(a <= mid) cmax(ans , query(a , b , l , mid , rt << 1)) ;
      if(b > mid) cmax(ans , query(a , b , mid + 1 , r , rt << 1 | 1)) ;
      return ans ;
    }
    class LCT {
    public : int rev[N] ; int fa[N] ; int ch[N][2] ;
    #define ls(x) ch[x][0]
    #define rs(x) ch[x][1]
      inline bool isroot(int x) { return ls(fa[x]) != x && rs(fa[x]) != x ; }
      inline bool getr(int x) { return rs(fa[x]) == x ; }
      inline void pushr(int x) { if(! rev[x]) return ; swap(ls(x) , rs(x)) ; rev[ls(x)] ^= 1 ; rev[rs(x)] ^= 1 ; rev[x] ^= 1 ; }
      inline void rotate(int x) { int y = fa[x] , z = fa[y] ; int k = getr(x) ;
        if(! isroot(y)) ch[z][getr(y)] = x ; fa[x] = z ; ch[y][k] = ch[x][k ^ 1] ; fa[ch[x][k ^ 1]] = y ; ch[x][k ^ 1] = y ; fa[y] = x ;
      }
      inline void pushall(int x) { if(! isroot(x)) pushall(fa[x]) ; pushr(x) ;}
      inline void splay(int x) { pushall(x) ; while(! isroot(x)) { int y = fa[x] ; if(! isroot(y)) rotate(getr(x) ^ getr(y) ? x : y) ; rotate(x) ; } }
      inline int findroot(int x) {
        while(ls(x)) x = ls(x) ; return x ;
      }
      inline void access(int x) { int son = 0 ;
        for( int tp = 0 ; x ; tp = x , x = fa[tp]) { splay(x) ;
          if(rs(x)) son = findroot(rs(x)) , update(L[son] , R[son] , 1 , n , 1 , 1) ;
          if(rs(x) = tp) { son = findroot(tp) ; update(L[son] , R[son] , 1 , n , 1 , - 1) ; }
          rs(x) = tp ;
        }
      }
    } lct ;
    struct node { int v , nxt ; } e[N << 1] ;
    int head[N] , cnt = 0 ;
    inline void add(int u , int v) { e[++ cnt].v = v ; e[cnt].nxt = head[u] ; head[u] = cnt ; }
    int fa[N] ; int size[N] ; int son[N] ;
    inline void Dfs(int u) { size[u] = 1 ; L[u] = ++ tot ; rev[tot] = u ;
      for(register int i = head[u] ; i ; i = e[i].nxt) {
        int v = e[i].v ; if(v == fa[u]) continue ;
        fa[v] = lct.fa[v] = u ; d[v] = d[u] + 1 ; Dfs(v) ; size[u] += size[v] ;
        if(size[v] > size[son[u]]) son[u] = v ;
      } R[u] = tot ;
    }
    int top[N] ;
    inline void Dfs2(int u , int tp) { top[u] = tp ;
      if(! son[u]) return ; Dfs2(son[u] , tp) ;
      for(register int i = head[u] ; i ; i = e[i].nxt) { int v = e[i].v ;
        if(v == fa[u] || v == son[u]) continue ; Dfs2(v , v) ;
      }
    }
    inline int lca(int x , int y) { int fx = top[x] , fy = top[y] ;
      while(fx ^ fy) { if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ; x = fa[fx] , fx = top[x] ; }
      if(d[x] > d[y]) swap(x , y) ;
      return x ;
    }
    signed main() { read(n , m) ;
      for(register int i = 1 ; i <= n - 1 ; i ++) { int u , v ; read(u , v) ; add(u , v) ; add(v , u) ;}
      d[1] = 1 ; Dfs(1) , Dfs2(1 , 1) ; build(1 , n , 1) ;
      for(register int i = 1 ; i <= m ; i ++) { int opt , x , y ; read(opt) ;
        if(opt == 1) { read(x) ; lct.access(x) ; }
        if(opt == 2) { read(x , y) ; int Lca = lca(x , y) ;
          int ans = query(L[x] , L[x] , 1 , n , 1) ; int ans2 = query(L[y] , L[y] , 1 , n , 1) ; int ans3 = query(L[Lca] , L[Lca] , 1 , n , 1) ;
          print(ans + ans2 - 2 * ans3 + 1 , '
    ') ;
        }
        if(opt == 3) { read(x) ; int ans = query(L[x] , R[x] , 1 , n , 1) ; print(ans , '
    ') ; }
      }
      return 0 ;
    }
    
  • 相关阅读:
    重读APUE(7)-link/unlink与mkdir/rmdir
    重读APUE(6)-umask
    社交系统中用户好友关系数据库设计
    修改Web项目的名称后,在TomCat中部署项目,项目的名称还是与原来相同的解决方案
    域名解析TTL是什么意思 TTL值设置为多少合适?
    mysql权限控制—新建用户允许其远程连接
    毕业设计技术方向(转载)
    统一资源定位符URL的组成
    开发中model,entity和pojo的区别
    要不要签三方协议
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/11716668.html
Copyright © 2020-2023  润新知