• BZOJ 3307: 雨天的尾巴


    用权值线段树维护最大值和其位置,树上差分作标记

    再在树上线段树合并

    这里有两个结论

    • 树上差分后,子树中每个孩子的值之和就是当前节点的值
    • 如果刚开始只有一个叶子节点的线段树有n个,那么合并成一棵线段树的复杂度为$O(nlogn)$
      1 #include <bits/stdc++.h>
      2 using namespace std;
      3  
      4 #define N 100010
      5 int n, q;
      6 int x[N], y[N], z[N];
      7 struct Graph
      8 {
      9     struct node
     10     {
     11         int to, nx;
     12         node() {}
     13         node(int to, int nx) : to(to), nx(nx) {} 
     14     }a[N << 2];
     15     int head[N], pos;
     16     void add(int u, int v)
     17     {
     18         a[++pos] = node(v, head[u]); head[u] = pos;
     19         a[++pos] = node(u, head[v]); head[v] = pos;
     20     }
     21 }G;
     22 #define erp(u) for (int it = G.head[u], v = G.a[it].to; it; it = G.a[it].nx, v = G.a[it].to)
     23  
     24 int b[N];
     25 void Hash()
     26 {
     27     b[0] = 0;
     28     for (int i = 1; i <= q; ++i) b[++b[0]] = z[i];
     29     sort(b + 1, b + 1 + b[0]);
     30     b[0] = unique(b + 1, b + 1 + b[0]) - b - 1;
     31     for (int i = 1; i <= q; ++i) z[i] = lower_bound(b + 1, b + 1 + b[0], z[i]) - b;  
     32 }
     33  
     34 int fa[N], deep[N], sze[N], son[N], top[N];
     35 void DFS(int u)
     36 {
     37     sze[u] = 1;
     38     erp(u) if (v != fa[u])
     39     {
     40         fa[v] = u;
     41         deep[v] = deep[u] + 1;
     42         DFS(v);
     43         sze[u] += sze[v];
     44         if (!son[u] || sze[v] > sze[son[u]]) son[u] = v;
     45     }
     46 }
     47  
     48 void getpos(int u, int sp)
     49 {
     50     top[u] = sp;
     51     if (!son[u]) return;
     52     getpos(son[u], sp);
     53     erp(u) if (v != fa[u] && v != son[u])
     54         getpos(v, v);
     55 }
     56  
     57 int lca(int u, int v)
     58 {
     59     while (top[u] != top[v])
     60     {
     61         if (deep[top[u]] < deep[top[v]]) swap(u, v);
     62         u = fa[top[u]];
     63     }
     64     return deep[u] > deep[v] ? v : u;
     65 }
     66  
     67 namespace SEG
     68 {
     69     #define M N * 70
     70     int T[N], lt[M], rt[M], Max[M], pos[M], cnt;
     71     void pushup(int now)
     72     {
     73         int ls = lt[now], rs = rt[now];
     74         if (Max[ls] >= Max[rs])
     75         {
     76             Max[now] = Max[ls];
     77             pos[now] = pos[ls];
     78         }
     79         else
     80         {
     81             Max[now] = Max[rs];
     82             pos[now] = pos[rs];
     83         }
     84     }
     85     void update(int &now, int l, int r, int loc, int v)
     86     {
     87         if (!now) now = ++cnt;
     88         if (l == r)
     89         {
     90             Max[now] += v;
     91             pos[now] = l; 
     92             return;
     93         }
     94         int mid = (l + r) >> 1;
     95         if (loc <= mid) update(lt[now], l, mid, loc, v);
     96         else update(rt[now], mid + 1, r, loc, v); 
     97         pushup(now);
     98     }
     99     int merge(int now, int pre, int l, int r)
    100     {
    101         if (!now | !pre) return now | pre;
    102         if (l == r)
    103         {
    104             Max[now] += Max[pre];
    105             pos[now] = l;
    106             return now;
    107         }
    108         int mid = (l + r) >> 1; 
    109         if (lt[now] | lt[pre]) lt[now] = merge(lt[now], lt[pre], l, mid); 
    110         if (rt[now] | rt[pre]) rt[now] = merge(rt[now], rt[pre], mid + 1, r);  
    111         pushup(now);
    112         return now;
    113     }
    114 }
    115  
    116 int ans[N];
    117 void solve(int u)
    118 {
    119     erp(u) if (v != fa[u]) 
    120     {
    121         solve(v);
    122         SEG::T[u] = SEG::merge(SEG::T[u], SEG::T[v], 1, b[0]);
    123     }
    124     int Pos = SEG::pos[SEG::T[u]];
    125     ans[u] = Pos ? b[Pos] : 0;
    126 }
    127 
    128 int main()
    129 {
    130     while (scanf("%d%d", &n, &q) != EOF)
    131     {
    132         for (int i = 1, u, v; i < n; ++i)
    133         {
    134             scanf("%d%d", &u, &v);
    135             G.add(u, v);
    136         }
    137         fa[1] = 0; DFS(1); getpos(1, 1);
    138         for (int i = 1; i <= q; ++i) scanf("%d%d%d", x + i, y + i, z + i); Hash();
    139         for (int i = 1; i <= q; ++i)
    140         {
    141             int LCA = lca(x[i], y[i]);
    142             SEG::update(SEG::T[x[i]], 1, b[0], z[i], 1);
    143             SEG::update(SEG::T[y[i]], 1, b[0], z[i], 1);
    144             SEG::update(SEG::T[LCA], 1, b[0], z[i], -1);
    145             if (fa[LCA]) SEG::update(SEG::T[fa[LCA]], 1, b[0], z[i], -1);
    146         }
    147         solve(1);
    148         for (int i = 1; i <= n; ++i) printf("%d
    ", ans[i]);
    149     }
    150     return 0;
    151 }
    152  
    View Code
  • 相关阅读:
    RxSwift 核心
    用 @media 控制图片显示大小
    关于媒体查询 @media 的用法
    再次搞懂弹性盒模型
    由淘宝想起,在css无法加载的情况下 依旧可以点击链接调整
    nth-child()和nth-of-type 用法
    如何消除img间的默认间隙
    由淘宝鼠标经过显示头像想起的 定位分析
    水平居中和垂直居中
    position 和 transform【鼠标经过显示一个div滑过】&导航效果应用 以及定位自己的总结
  • 原文地址:https://www.cnblogs.com/Dup4/p/10120069.html
Copyright © 2020-2023  润新知