[Vani有约会]雨天的尾巴 (线段树合并)

题目链接


Solution

树上差分+线段树合并.
在每个节点上维护一棵权值线段树.
然后如果需要修改 (x,y) 两点,则在 (x) 处和 (y) 处分别加上 (1) 的权值.
然后在 (lca(x,y)) 以及 (fa[lca(x,y)]) 处减掉 (1) .
最后面 (dfs) 从下往上更新.

由于每一次维护只维护四个点的值,且每次在每一棵树上也只会修改一条链的值.
每次操作时间复杂度和空间复杂度均为 (O(4*logn)) .
所以整体时间和空间复杂度即为 (O(4*nlogn)) .可以过.

Code

#include<bits/stdc++.h>
#define N 100008
#define in(x) x=read()
using namespace std;
struct sj{int to,next;}a[N*2];
int head[N*2],size,n,q;
int dep[N*2],fa[N*2][20],v[N*2];
int T[N*2],L[N*60],R[N*60],rans[N*2];
int num[N*60],rt,tot,m,Ans[N*60],ans[N*60];

int read()
{
    char ch=getchar(); int f=1,w=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    return f*w;
}

void add(int x,int y)
{
    a[++size].to=y;
    a[size].next=head[x];
    head[x]=size;
}

void dfs(int x,int fr)
{
    for(int i=head[x];i;i=a[i].next){
        int tt=a[i].to;
        if(tt==fr)continue;
        dep[tt]=dep[x]+1;
            fa[tt][0]=x;
        dfs(tt,x);
    }
}

int lca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    for(int i=19;i>=0;i--)
        if(dep[fa[x][i]]>=dep[y])
        x=fa[x][i];
    if(x==y) return x;
    for(int i=19;i>=0;i--)
        if(fa[x][i]!=fa[y][i])
        x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}

void pushup(int node)
{
    if(ans[L[node]]>=ans[R[node]])
    ans[node]=ans[L[node]],Ans[node]=Ans[L[node]];
    else 
    ans[node]=ans[R[node]],Ans[node]=Ans[R[node]];
}
void update(int &node,int l,int r,int pos,int v)
{
    if(!node) node=++tot;
    if(l==r) {ans[node]+=v;Ans[node]=l;return;}
    int mid=(l+r)/2;
    if(pos<=mid) update(L[node],l,mid,pos,v);
    else update(R[node],mid+1,r,pos,v);
    if(l!=r)
    pushup(node);
}
int merge(int x,int y,int l,int r)
{
    if(l==r&&x&&y) ans[x]+=ans[y];
    if(!x||!y) return x+y;
    int mid=(l+r)/2;
    L[x]=merge(L[x],L[y],l,mid);
    R[x]=merge(R[x],R[y],mid+1,r);
    if(l!=r)
    pushup(x);
    return x;
}
void Dfs(int x,int fr)
{
    for(int i=head[x];i;i=a[i].next){
        int tt=a[i].to;
        if(tt==fr)continue;
        Dfs(tt,x);
        T[x]=merge(T[x],T[tt],1,N);
    }
    if(ans[T[x]]>0)
    rans[x]=Ans[T[x]];
}

int main()
{
    in(n),in(q);
    for(int i=1;i<n;i++){
        int x,y; in(x),in(y);
        add(x,y),add(y,x);
    }
    dep[1]=1; dfs(1,0);
    for(int j=1;j<=19;j++)
    for(int i=1;i<=n;i++)
        fa[i][j]=fa[fa[i][j-1]][j-1];	
        
     for(int i=1;i<=q;i++)
    {
    	int x,y,z;
    	in(x),in(y),in(z);
        int pp=lca(x,y);
        update(T[x],1,N,z,1);
        update(T[y],1,N,z,1);
        update(T[pp],1,N,z,-1);
        update(T[fa[pp][0]],1,N,z,-1);
    }
    Dfs(1,0);
    for(int i=1;i<=n;i++)
    printf("%d
",rans[i]);
}
原文地址:https://www.cnblogs.com/Kv-Stalin/p/9773257.html