zoukankan      html  css  js  c++  java
  • P5168 xtq玩魔塔 [克鲁斯卡尔重构树+带修莫队]

    P5168 xtq玩魔塔

    又是码农题…

    利用克鲁斯卡尔重构树的性质

    我们就可以得出 (dep) 值小的,肯定比 (dep) 大的值要优。
    于是第二问就可以直接 LCA 求出来了…
    至于第三问,dfs序一下,然后求子树…考虑莫队
    修改直接带修莫队,没了。

    #include <bits/stdc++.h>
    using namespace std ;
    int min(int x , int y) { return x < y ? x : y ; }
    void swap(int & x , int & y) { x ^= y ^= x ^= y ; }
    int read() {
      int x = 0 , f = 1 ; char c = getchar() ;
      while(c < '0' || c > '9') { if(c == '-') f = -1 ; c = getchar() ; }
      while(c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + (c & 15) ; c = getchar() ; }
      return x * f ;
    }
    void print(int x) {
      char _st[20] ; int tp = 0 ;
      if(! x) { putchar('0') ; }
      while(x) { _st[++ tp] = (x % 10) ^ 48 ; x /= 10 ; }
      while(tp) { putchar(_st[tp --]) ; }
      putchar('
    ') ;
    }
    const int N = 1e5 + 10 ;
    const int M = 3e5 + 10 ;
    const int Q = 2e5 + 10 ;
    struct Edge { int u , v , w ; } E[M] ;
    struct _Link { int v , nxt ; } e[N << 1] ;
    struct Change { int pos , col ; } qc[Q] ;
    struct Qry { int l , r , id , t ; } qr[Q] ;
    int n , m , q , change_cnt = 0 , qry_cnt = 0 , len = 0 ;
    int col[N] , fa[N << 1] , val[N << 1] , head[N << 1] , cnt = 0 , f[N << 1][22] , d[N << 1] ;
    int rev[N << 1] , dfn[N << 1] , sz[N << 1] , idx = 0 , ans[Q] , _cnt[N << 1] , bl[N] ;
    void Link(int u , int v) { e[++ cnt] = { v , head[u] } ; head[u] = cnt ; }
    void dfsfa(int u) {
      for(int i = head[u] ; i ; i = e[i].nxt) { d[e[i].v] = d[f[e[i].v][0] = u] + 1 ; dfsfa(e[i].v) ; }
    }
    void dfssz(int u) {
      if(u <= n) { rev[dfn[u] = ++ idx] = u ; sz[u] = 1 ; } else dfn[u] = 1e9 ;
      for(int i = head[u] ; i ; i = e[i].nxt) { dfssz(e[i].v) ; sz[u] += sz[e[i].v] ; dfn[u] = min(dfn[u] , dfn[e[i].v]) ; }
    }
    int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]) ; }
    void Kruskal() {
      int tot = n ; sort(E + 1 , E + m + 1 , [](Edge x , Edge y) { return x.w < y.w ; }) ;
      for(int i = 1 ; i <= (n << 1) ; i ++) fa[i] = i ;
      for(int i = 1 ; i <= m ; i ++) {
        int u = find(E[i].u) , v = find(E[i].v) ;
        if(u ^ v) { ++ tot ; val[fa[tot] = fa[u] = fa[v] = tot] = E[i].w ; Link(tot , u) ; Link(tot , v) ; }
      } dfsfa(tot) ; dfssz(tot) ;
    }
    int Lca(int u , int v) {
      if(d[u] < d[v]) swap(u , v) ;
      for(int i = 20 ; ~ i ; i --) if(d[f[u][i]] >= d[v]) u = f[u][i] ; if(u == v) return u ;
      for(int i = 20 ; ~ i ; i --) if(f[u][i] ^ f[v][i]) { u = f[u][i] ; v = f[v][i] ; } return f[u][0] ;
    }
    int gettop(int u , int _val) { for(int i = 20 ; ~ i ; i --) if(f[u][i] && val[f[u][i]] <= _val) u = f[u][i] ; return u ; }
    int Ans = 0 ;
    void ins(int x) { if(++ _cnt[x] == 1) ++ Ans ; }
    void del(int x) { if(-- _cnt[x] == 0) -- Ans ; }
    void modify(int x , int now) {
      if(qc[x].pos >= qr[now].l && qc[x].pos <= qr[now].r) { del(col[rev[qc[x].pos]]) ; ins(qc[x].col) ; }
      swap(qc[x].col , col[rev[qc[x].pos]]) ;
    }
    void Solve() {
      for(int j = 1 ; j <= 20 ; j ++)
        for(int i = 1 ; i <= (n << 1) ; i ++) f[i][j] = f[f[i][j - 1]][j - 1] ;
      for(int i = 1 ; i <= q ; i ++) {
        int opt = read() ;
        if(opt == 1) { int pos = read() , col = read() ; qc[++ change_cnt] = { dfn[pos] , col } ; }
        if(opt == 2) { ans[++ qry_cnt] = val[Lca(read() , read())] ; }
        if(opt == 3) { ++ qry_cnt ; int x = read() , top = gettop(x , read()) ; qr[++ len] = { dfn[top] , dfn[top] + sz[top] - 1 , qry_cnt , change_cnt} ; }
      }
      vector < int > b ; for(int i = 1 ; i <= n ; i ++) b.push_back(col[i]) ;
      for(int i = 1 ; i <= change_cnt ; i ++) b.push_back(qc[i].col) ;
      sort(b.begin() , b.end()) ; b.erase(unique(b.begin() , b.end()) , b.end()) ;
      for(int i = 1 ; i <= n ; i ++) col[i] = lower_bound(b.begin() , b.end() , col[i]) - b.begin() ;
      for(int i = 1 ; i <= change_cnt ; i ++) qc[i].col = lower_bound(b.begin() , b.end() , qc[i].col) - b.begin() ;
      int block = sqrt(n * (2.0 / 3.0)) ; for(int i = 1 ; i <= n ; i ++) bl[i] = (i - 1) / block + 1 ;
      sort(qr + 1 , qr + len + 1 , [](Qry x , Qry y) {
        if(bl[x.l] ^ bl[y.l]) return x.l < y.l ;
        if(bl[x.r] ^ bl[y.r]) return x.r < y.r ;
        return x.t < y.t ;
      }) ;
      int l = 1 , r = 0 , now_t = 0 ;
      for(int i = 1 ; i <= len; i ++) {
        while(l > qr[i].l) ins(col[rev[-- l]]) ; while(r < qr[i].r) ins(col[rev[++ r]]) ;
        while(l < qr[i].l) del(col[rev[l ++]]) ; while(r > qr[i].r) del(col[rev[r --]]) ;
        while(now_t < qr[i].t) modify(++ now_t , i) ; while(now_t > qr[i].t) modify(now_t -- , i) ;
        ans[qr[i].id] = Ans ;
      }
      for(int i = 1 ; i <= qry_cnt ; i ++) print(ans[i]) ;
    }
    signed main() {
      n = read() ; m = read() ; q = read() ;
      for(int i = 1 ; i <= n ; i ++) { col[i] = read() ; }
      for(int i = 1 ; i <= m ; i ++) { int u = read() , v = read() , w = read() ; E[i] = { u , v , w } ; }
      Kruskal() ; Solve() ;
      return 0 ;
    }
    
    
  • 相关阅读:
    Elasticsearch 内存配置应用案例
    shell进阶篇之字典和数组结合应用案例
    shell进阶篇之数组应用案例
    nginx的负载均衡
    nginx的反向代理
    ajax的几种使用
    springboot整合Redis
    java的Spring中@Value注解的使用
    Redis的五种数据类型
    冒泡排序
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/11983101.html
Copyright © 2011-2022 走看看