zoukankan      html  css  js  c++  java
  • [BZOJ 3307] 雨天的尾巴

    [题目链接]

            https://www.lydsy.com/JudgeOnline/problem.php?id=3307

    [算法]

            考虑树上差分 :

            在路径x-y上每个点放一个物品c , 等价于 :

            在x到根节点的路径上放一个物品c , 在y到根节点的路径上放一个物品c ,

       然后在x和y的最近公共祖先到根节点的路径上删除一个物品c , 在x和y的最近公共祖先的父亲到根节点的路径上删除一个物品c

            不妨对于每个点构建一棵权值线段树

            在DFS计算答案的时候线段树合并 , 即可

            时间复杂度 : O(NlogN)(N , M同阶)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    const int MAXP = 5000005;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    struct edge
    {
          int to , nxt;
    } e[N << 1];
    
    int n , m , tot , len;
    int rt[N] , depth[N] , head[N] , ans[N] , size[N] , son[N] , top[N] , fa[N] , tmp[N] , x[N] , y[N] , z[N];
    
    struct Segment_Tree
    {
          int sz;
          Segment_Tree()
          {
              sz = 0;        
          }        
          struct Node
          {
              int mx , pos;
              int lc , rc;
          } a[MAXP];
          inline int merge(int x , int y , int l , int r)
          {
                  if (x == 0 || y == 0) return x + y;
              if (l == r)
              {
                  a[x].mx += a[y].mx;
                  a[x].pos = l;
              }
              int mid = (l + r) >> 1;
              a[x].lc = merge(a[x].lc , a[y].lc , l , mid);
              a[x].rc = merge(a[x].rc , a[y].rc , mid + 1 , r);
              update(x);
              return x;
          }
          inline void update(int x)
          {
              if (!a[x].lc && !a[x].rc) return;
              if (a[x].lc && !a[x].rc)
              {
                    a[x].mx = a[a[x].lc].mx;
                    a[x].pos = a[a[x].lc].pos;
              }
              if (!a[x].lc && a[x].rc)
              {
                    a[x].mx = a[a[x].rc].mx;
                    a[x].pos = a[a[x].rc].pos;
              }
              if (a[x].lc && a[x].rc)
              {
                  if (a[a[x].lc].mx >= a[a[x].rc].mx)
                  {
                      a[x].mx = a[a[x].lc].mx;
                      a[x].pos = a[a[x].lc].pos;
                  } else
                  {
                      a[x].mx = a[a[x].rc].mx;
                      a[x].pos = a[a[x].rc].pos;
                  }
              }
          }
          inline void modify(int &now , int l , int r , int x , int value)
          {
              if (!now) now = ++sz;
              if (l == r)
              {
                  a[now].mx += value;
                  a[now].pos = l;
                  return;
              }
              int mid = (l + r) >> 1;
              if (mid >= x) modify(a[now].lc , l , mid , x , value);
              else modify(a[now].rc , mid + 1 , r , x , value);
              update(now);
          }
          inline int query(int x)
          {
              if (a[rt[x]].mx <= 0) return 0;
              else return a[rt[x]].pos;
          }
    } SGT;
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v)
    {
        ++tot;
        e[tot] = (edge){v , head[u]};
        head[u] = tot;
    }
    inline void dfs1(int u , int father)
    {
        depth[u] = depth[father] + 1;
        fa[u] = father;
        size[u] = 1;
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (v == father) continue;
            dfs1(v , u);
            size[u] += size[v];
            if (size[v] > size[son[u]]) son[u] = v;
        }
    }
    inline int dfs2(int u , int fa , int t)
    {
            top[u] = t;
            if (son[u]) dfs2(son[u] , u , t);
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (v == fa || v == son[u]) continue;
                    dfs2(v , u , v);
            }
    }
    inline int lca(int x , int y)
    {
        while (top[x] != top[y])
        {
                if (depth[top[x]] > depth[top[y]]) swap(x , y);
                y = fa[top[y]];
            }
            if (depth[x] < depth[y]) return x;
            else return y;
    }
    inline void calc(int u , int father)
    {
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to;
            if (v == father) continue;
            calc(v , u);
            rt[u] = SGT.merge(rt[u] , rt[v] , 1 , len);        
        }        
        ans[u] = tmp[SGT.query(u)];
    }
    
    int main()
    {
            
        read(n); read(m);
        for (int i = 1; i < n; i++)
        {
            int x , y;
            read(x); read(y);
            addedge(x , y);
            addedge(y , x);
        }
        dfs1(1 , 0);
        dfs2(1 , 0 , 1); 
        for (int i = 1; i <= m; i++)
        {
                read(x[i]);
                read(y[i]);
                read(z[i]);
                tmp[i] = z[i];
            }
            sort(tmp + 1 , tmp + m + 1);
            len = unique(tmp + 1 , tmp + m + 1) - tmp - 1;
            for (int i = 1; i <= m; i++) z[i] = lower_bound(tmp + 1 , tmp + len + 1 , z[i]) - tmp;
        for (int i = 1; i <= m; i++)
        {
            SGT.modify(rt[x[i]] , 1 , len , z[i] , 1);
            SGT.modify(rt[y[i]] , 1 , len , z[i] , 1);
            int Lca = lca(x[i] , y[i]);
            SGT.modify(rt[Lca] , 1 , len , z[i] , -1);
            if (fa[Lca]) SGT.modify(rt[fa[Lca]] , 1 , len , z[i] , -1);        
        }
        calc(1 , 0);
        for (int i = 1; i <= n; i++) printf("%d
    " , ans[i]);
        
        return 0;
        
    }

             

  • 相关阅读:
    group by与聚合函数
    表联结
    项目延期 怎样规避风险
    虚拟机安装linux系统
    Cannot truncate a table referenced in a foreign key constraint
    李航--《统计学习方法总结》
    CART算法
    北航学长分享交流笔记
    CentOS7导入MySql数据表结构并显示表结构
    RedHat7安装mysql5.7数据库
  • 原文地址:https://www.cnblogs.com/evenbao/p/10200767.html
Copyright © 2011-2022 走看看