[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\n" , ans[i]);
    
    return 0;
    
}

 

         

posted @ 2018-12-30 21:30  evenbao  阅读(225)  评论(0编辑  收藏  举报