• bzoj4551 [TJOI2016&HEOI2016]树


    bzoj4551 [TJOI2016&HEOI2016]树

    给定一棵有根树,请支持一下两种操作:

    • 标记一个点
    • 询问一个点最近一个打了标记的祖先

    (n, mleq10^5)

    线段树


    首先用 (dfs) 序转换为序列问题,用线段树动态维护

    打标记按照原树 (dep) 更新答案

    实现时可以将点上的答案与 (tag) 合并

    时间复杂度 (O(nlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    #define mid ((s + t) >> 1)
    #define lson k << 1, s, mid
    #define rson k << 1 | 1, mid + 1, t
    const int maxn = 1e5 + 10;
    int val[maxn << 2];
    int n, m, sz[maxn], dep[maxn], tid[maxn];
    
    vector <int> e[maxn];
    
    int dfs(int u, int f) {
      static int now;
      tid[u] = ++now;
      int tmp = int(e[u].size());
      for (int i = 0; i < tmp; i++) {
        int v = e[u][i];
        if (v != f) {
          dep[v] = dep[u] + 1;
          sz[u] += dfs(v, u);
        }
      }
      return ++sz[u];
    }
    
    void pushtag(int k, int x) {
      if (dep[val[k]] < dep[x]) {
        val[k] = x;
      }
    }
    
    void pushdown(int k) {
      pushtag(k << 1, val[k]);
      pushtag(k << 1 | 1, val[k]);
    }
    
    void build(int k, int s, int t) {
      if (s == t) {
        val[k] = 1; return;
      }
      build(lson), build(rson);
    }
    
    void upd(int k, int s, int t, int l, int r, int x) {
      if (dep[x] < dep[val[k]]) return;
      if (l <= s && t <= r) {
        pushtag(k, x); return;
      }
      pushdown(k);
      if (l <= mid) upd(lson, l, r, x);
      if (r > mid) upd(rson, l, r, x);
    }
    
    int query(int pos) {
      int k = 1, s = 1, t = n;
      while (s < t) {
        pushdown(k);
        if (pos <= mid) {
          k <<= 1, t = mid;
        } else {
          k = k << 1 | 1, s = mid + 1;
        }
      }
      return val[k];
    }
    
    int main() {
      scanf("%d %d", &n, &m);
      for (int i = 1, u, v; i < n; i++) {
        scanf("%d %d", &u, &v);
        e[u].push_back(v), e[v].push_back(u);
      }
      dfs(1, 0), build(1, 1, n);
      char c; int u;
      while (m--) {
        scanf("%s %d", &c, &u);
        if (c == 'C') {
          upd(1, 1, n, tid[u], tid[u] + sz[u] - 1, u);
        } else {
          printf("%d
    ", query(tid[u]));
        }
      }
      return 0;
    }
    
  • 相关阅读:
    MDL中捕获到损坏的页表页
    跟踪MmSt分页池使用情况
    了解NTFS压缩
    如何跟踪高CPU在用户模式应用程序-现场调试!
    如何与转储文件建立丰富多彩的关系
    Kernel Stack Overflows
    非分页池的消耗
    MBR反汇编
    LPC (Local procedure calls)(二)内核调试扩展
    LPC (Local procedure calls) (一)数据结构
  • 原文地址:https://www.cnblogs.com/Juanzhang/p/10565839.html
Copyright © 2020-2023  润新知