• [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]);
    }
    
  • 相关阅读:
    如何用conda安装软件|处理conda安装工具的动态库问题
    用 Anaconda 完美解决 Python2 和 python3 共存问题
    转录组数据库介绍
    突变注释工具SnpEff,Annovar,VEP,oncotator比较分析--转载
    BioConda--转载
    生信软件的好帮手-bioconda--转载
    一些WGS健康体检网站和公司
    基于R进行相关性分析--转载
    R语言 sub与gsub函数的区别
    Docker安装
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9773257.html
Copyright © 2020-2023  润新知