BZOJ3307 雨天的尾巴

题目链接:戳我

树上链修改->差分
每一个节点都开一个权值线段树,最后从下往上合并qwq

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define MAXN 200010
using namespace std;
int t,n,m,cnt,cur_cnt;
int maxx[MAXN<<5],head[MAXN],ans[MAXN],dep[MAXN],x[MAXN],y[MAXN],z[MAXN],cur[MAXN],id[MAXN];
int fa[MAXN][21],rt[MAXN],ls[MAXN<<5],rs[MAXN<<5];
struct Edge{int nxt,to;}edge[MAXN<<1];
inline void add(int from,int to){edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;}
inline void push_up(int x){maxx[x]=max(maxx[ls[x]],maxx[rs[x]]);}
inline void modify(int &x,int l,int r,int pos,int k)
{
    if(!x) x=++cnt;
    if(l==r) {maxx[x]+=k;return;}
    int mid=(l+r)>>1;
    if(pos<=mid) modify(ls[x],l,mid,pos,k);
    else modify(rs[x],mid+1,r,pos,k);
    push_up(x);
}
inline int merge(int x,int y,int l,int r)
{
    if(!x||!y) return x+y;
    if(l==r) {maxx[x]+=maxx[y];return x;}
    int mid=(l+r)>>1;
    ls[x]=merge(ls[x],ls[y],l,mid);
    rs[x]=merge(rs[x],rs[y],mid+1,r);
    push_up(x);
    return x;
}
inline int query(int x,int l,int r)
{
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(maxx[x]==maxx[ls[x]]) return query(ls[x],l,mid);
    else return query(rs[x],mid+1,r);
}
inline void dfs1(int x,int ff)
{
    for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==fa[x][0]) continue;
        dep[v]=dep[x]+1;fa[v][0]=x;
        dfs1(v,x);
    }
}
inline int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    int tt=dep[x]-dep[y];
    for(int i=0;i<21;i++)
        if(tt&(1<<i))
            x=fa[x][i];
    if(x==y) return x;
    for(int i=20;i>=0;i--)
        if(fa[x][i]!=fa[y][i])
            x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
inline void solve(int x,int ff)
{
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==ff) continue;
        solve(v,x);
        rt[x]=merge(rt[x],rt[v],1,cur_cnt);
    }
    if(!maxx[rt[x]]) ans[x]=0;
    else ans[x]=id[query(rt[x],1,cur_cnt)];
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    for(int i=1;i<=m;i++) scanf("%d%d%d",&x[i],&y[i],&z[i]);
    memcpy(cur,z,sizeof(z));
    sort(&cur[1],&cur[1+m]);
    cur_cnt=unique(&cur[1],&cur[1+m])-cur-1;
    for(int i=1;i<=m;i++)
    {
        int kkk=lower_bound(&cur[1],&cur[1+cur_cnt],z[i])-cur;
        id[kkk]=z[i];
        z[i]=kkk;
    }
    dfs1(1,1);
    for(int i=1;i<=m;i++)
    {
        modify(rt[x[i]],1,cur_cnt,z[i],1);
        modify(rt[y[i]],1,cur_cnt,z[i],1);
        int LCA=lca(x[i],y[i]);
        modify(rt[LCA],1,cur_cnt,z[i],-1);
        if(fa[LCA]) 
            modify(rt[fa[LCA][0]],1,cur_cnt,z[i],-1);
    }
    solve(1,1);
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
}
posted @ 2019-01-28 20:33  风浔凌  阅读(94)  评论(0编辑  收藏  举报