• Luogu_P4556 雨天的尾巴【题解】树上差分 线段树合并


    题面:https://www.luogu.com.cn/problem/P4556

    对于在一条(x,y)路径上将z加1。

    就可以树上差分。

    x和y都是加1。lca是减1,lca的father也是减1。

    但是由于又有很多种不一样的种类。

    还需要每个点维护一个线段树。

    合并的时候求哪个种类是max。

    最后统计答案dfs。

    思路简单,主要是代码长。 

    代码如下:

    #pragma-GCC-optimize("O2,Ofast,inline,unroll-all-loops,-ffast-math")
    #pragma-GCC-target("avx,sse2,sse3,sse4,popcnt")
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100010;
    int tt,n,m;
    struct node{
        int nxt,to;
        #define nxt(x) e[x].nxt
        #define to(x) e[x].to
    }e[maxn<<1];
    int head[maxn],tot,dep[maxn],f[maxn][21],rt[maxn],num,cnt,X[maxn],Y[maxn],Z[maxn],val[maxn],ans[maxn];
    inline void add(int x,int y){
        to(++tot)=y;
        nxt(tot)=head[x];head[x]=tot;
    }
    queue<int> q;
    inline long read(){
        long x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f*=-1;c=getchar();}
        while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
        return x*f;
    }
    inline void bfs(){
        q.push(1);dep[1]=1;
        while(q.size()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=nxt(i)){
                int to=to(i);
                if(dep[to]) continue;
                dep[to]=dep[x]+1;
                f[to][0]=x;
                for(int j=1;j<=tt;j++)
                    f[to][j]=f[f[to][j-1]][j-1];
                q.push(to);
            }
        }
    }
    inline int lca(int x,int y){
        if(dep[x]>dep[y]) swap(x,y);
        for(int i=tt;i>=0;i--)
            if(dep[f[y][i]] >= dep[x]) y=f[y][i];
        if(x==y) return x;
        for(int i=tt;i>=0;i--)
            if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    struct tree{
        int lc,rc,dt,tg;
    }t[maxn*80];
    void insert(int p,int l,int r,int vl,int d){
        if(l==r){
            t[p].dt+=d;
            t[p].tg=t[p].dt ? l : 0 ;
            return;
        }
        int mid=(l+r)>>1;
         if(vl<=mid){
             if(!t[p].lc) t[p].lc=++num;
             insert(t[p].lc,l,mid,vl,d);
         }else{
             if(!t[p].rc) t[p].rc=++num;
             insert(t[p].rc,mid+1,r,vl,d);
         }
         t[p].dt=max(t[t[p].lc].dt,t[t[p].rc].dt);
         t[p].tg=t[t[p].lc].dt>=t[t[p].rc].dt ? t[t[p].lc].tg : t[t[p].rc].tg;
    }
    int merge(int p,int q,int l,int r){
        if(!p) return q;
        if(!q) return p;
        if(l==r){
            t[p].dt+=t[q].dt;
            t[p].tg=t[p].dt ? l : 0;
            return p;
        }
        int mid=(l+r)>>1;
        t[p].lc=merge(t[p].lc,t[q].lc,l,mid);
        t[p].rc=merge(t[p].rc,t[q].rc,mid+1,r);
        t[p].dt=max(t[t[p].lc].dt,t[t[p].rc].dt);
        t[p].tg=t[t[p].lc].dt>=t[t[p].rc].dt ? t[t[p].lc].tg : t[t[p].rc].tg;
        return p;
    }
    void dfs(int x){
        for(int i=head[x];i;i=nxt(i)){
            int to=to(i);
            if(dep[to]<=dep[x]) continue;
            dfs(to);
            rt[x]=merge(rt[x],rt[to],1,cnt);
        }
        ans[x]=t[rt[x]].tg;
    }
    int main()
    {
        n=read(),m=read();
        tt=(int)(log(n)/log(2))+1;
        for(int i=1;i<n;i++){
            int x,y;x=read();y=read();
            add(x,y);add(y,x);
        }
        bfs();
        for(int i=1;i<=n;i++) rt[i]=++num;
        for(int i=1;i<=m;i++){
            X[i]=read();Y[i]=read();Z[i]=read();
            val[i]=Z[i];
        }
        sort(val+1,val+1+m);
        cnt=unique(val+1,val+1+m)-val-1;
        for(int i=1;i<=m;i++){
            int x=X[i],y=Y[i];
            int z=lower_bound(val+1,val+1+cnt,Z[i])-val;
            int lc=lca(x,y);
            insert(rt[x],1,cnt,z,1);
            insert(rt[y],1,cnt,z,1);
            insert(rt[lc],1,cnt,z,-1);
            if(f[lc][0]) insert(rt[f[lc][0]],1,cnt,z,-1);
        }
        dfs(1);
        for(int i=1;i<=n;i++) printf("%d
    ",val[ans[i]]);
        return 0;
    }
  • 相关阅读:
    用例图解析
    A B C D类网络地址
    B-树特征
    常用的中间代码
    UML图
    关于文件索引的一道习题
    数据流图的一些原则
    系统总线
    各种排序方法的时间复杂度、空间复杂度和稳定性统计表
    模拟银行自助终端系统
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11544029.html
Copyright © 2020-2023  润新知