雨天的尾巴

P4556雨天的尾巴

先考虑修改操作,因为要对$x \to y $ 路径上的每一个点的\(Z\) 类物品加一,所以我们考虑树上差分,在\(x点和y点\)\(+1\)然后在\(lca(x,y)\)\(fa_{lca(x,y)}\)位置\(-1\)
然后我们可以从叶子节点到根节点做一遍\(dfs\)每次把儿子线段树的每一个点合并到父亲线段树上,维护最大值和物品编号
不会线段树合并的可以看这个

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,C=1e5+5;
int hd[N],cnt,sz[N],son[N],top[N],tp[N],a[N],fa[N],dep[N],u,v,w,ps,n,m;
struct E {
    int to,nt;
}e[N << 1];
struct Tr {
    int clr,v,l,r;
}tr[10000007];
void add(int x,int y) {
    e[++cnt].to = y;
    e[cnt].nt = hd[x];
    hd[x] = cnt;
}
void dfs1(int x) {
    int y,maxs = 0;
    sz[x] = 1;
    for(int i=hd[x];i;i=e[i].nt) {
        y = e[i].to;
        if(y == fa[x] ) 
            continue;
        fa[y] = x;
        dep[y] = dep[x] + 1;
        dfs1(y);
        sz[x] += sz[y];
        if(sz[y] > maxs) {
            maxs = sz[y];
            son[x] = y;
        }
    }
}
void dfs2(int x) {
    if(son[x]) {
        top[son[x]] = top[x];
        dfs2(son[x]);
    }
    int y;
    for(int i=hd[x];i;i=e[i].nt) {
        y=e[i].to;
        if(y == fa[x] || y == son[x]) 
            continue;
        top[y] = y;
        dfs2(y);
    }
}
int lca(int x,int y) {
    while(top[x] != top[y]) {
        if(dep[fa[top[x]]] > dep[fa[top[y]]]) 
            swap(x,y);
        y = fa[top[y]];
    }
    if(dep[x] > dep[y])
        swap(x,y);
    return x;
}
void get_l(int p) {
    if(!tr[p].l)
        tr[p].l = ++ps;
}
void get_r(int p) {
    if(!tr[p].r)
        tr[p].r = ++ps;
}
void updata(int p) {
    if(tr[tr[p].l].v > tr[tr[p].r].v) {
        tr[p].v = tr[tr[p].l].v;
        tr[p].clr = tr[tr[p].l].clr;
    }
    else if(tr[tr[p].l].v < tr[tr[p].r].v){
        tr[p].v = tr[tr[p].r].v;
        tr[p].clr = tr[tr[p].r].clr;
    }
    else {
        tr[p].v = tr[tr[p].l].v;
        tr[p].clr = tr[tr[p].l].clr;
    }
}
void change(int p,int l,int r,int cl,int vl) {
    if(l==r) {
        tr[p].clr = cl;
        tr[p].v += vl;
    }
    else {
        int mid=l + r >> 1;
        if(cl <= mid) {
            get_l(p);
            change(tr[p].l,l,mid,cl,vl);
        }
        else {
            get_r(p);
            change(tr[p].r,mid+1,r,cl,vl);
        }
        updata(p);
    }
}
void Marge(int x,int y,int l,int r) {
    if(l == r) {
        tr[x].v+=tr[y].v;
    }
    else {
        int mid = l + r >> 1;
        if(!tr[x].l && tr[y].l) {
            tr[x].l = tr[y].l;
        }
        else if(tr[y].l && tr[x].l) {
            Marge(tr[x].l,tr[y].l,l,mid);
        }
        if(!tr[x].r && tr[y].r) {
            tr[x].r = tr[y].r;
        }
        else if(tr[y].r && tr[x].r) {
            Marge(tr[x].r,tr[y].r,mid+1,r);
        }
        updata(x);
    }
}
void fans(int x) {
    int y;
    for(int i=hd[x];i;i=e[i].nt) {
        y=e[i].to;
        if(fa[x] == y) 
            continue;
        fans(y);
        Marge(x,y,1,C);
    }
}
int main() {
    int la;
    scanf("%d%d",&n,&m);
    ps=n;
    for(int i=1;i<n;i++) {
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dep[1] = 1;
    dfs1(1);
    top[1] = 1;
    dfs2(1);
    for(int i=1;i<=m;i++) {
        scanf("%d%d%d",&u,&v,&w);
        change(u,1,C,w,1);
        change(v,1,C,w,1);
        la = lca(u,v);
        change(la,1,C,w,-1);
        change(fa[la],1,C,w,-1);
    }
    fans(1);
    for(int i=1;i<=n;i++)
    {
        if(tr[i].v)
            printf("%d\n",tr[i].clr);
        else 
            printf("0\n");
    }
    return 0;
}
posted @ 2023-03-22 19:51  2020fengziyang  阅读(21)  评论(0编辑  收藏  举报