P4556 雨天的尾巴

题目背景
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。

题目描述
首先村落里的一共有n座房屋,并形成一个树状结构。然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮。
然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。

输入格式
第一行两个正整数n,m,含义如题目所示。
接下来n-1行,每行两个数(a,b),表示(a,b)间有一条边。
再接下来m行,每行三个数(x,y,z),含义如题目所示。

输出格式
n行,第i行一个整数,表示第i座房屋里存放的最多的是哪种救济粮,如果有多种救济粮存放次数一样,输出编号最小的。
如果某座房屋里没有救济粮,则对应一行输出0。

输入输出样例
输入 #1 
5 3
1 2
3 1
3 4
5 3
2 3 3
1 5 2
3 3 3
输出 #1 
2
3
3
0
2
说明/提示
对于20%的数据,1 <= n, m <= 100
对于50%的数据,1 <= n, m <= 2000
对于100%的数据,1 <= n, m <= 100000, 1 <= a, b, x, y <= n, 1 <= z <= 100000

用树上差分,对于(x,y)这条路径,则在x,y处+1,在lca,fa(lca)处−1,然后再用线段树合并即可。

Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=200005,M=200000;
int n,m,Cnt,tot;
int Head[N],v[N<<1],Next[N<<1];
int dep[N],ans[N],root[N],fa[N][25],lc[N<<5],rc[N<<5];
pair<int,int>Max[N<<5];
void add(int x,int y){
    Cnt++;
    Next[Cnt]=Head[x];
    Head[x]=Cnt;
    v[Cnt]=y;
}
void dfs(int x){
    for(int i=1;i<=20;i++){
        fa[x][i]=fa[fa[x][i-1]][i-1];
    }
    for(int i=Head[x];i;i=Next[i]){
        int k=v[i];
        if(k!=fa[x][0]){
            fa[k][0]=x;
            dep[k]=dep[x]+1;
            dfs(k);
        }
    }
}
int lca(int x,int y){
    int i;
    if(dep[x]<dep[y]){
        swap(x,y);
    }
    for(i=20;~i;--i){
        if(dep[fa[x][i]]>=dep[y]){
            x=fa[x][i];
        }
    }
    if(x==y){
        return x;
    }
    for(i=20;~i;--i){
        if(fa[x][i]!=fa[y][i]){
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    return fa[x][0];
}
void insert(int &root,int l,int r,int pos,int num){
    if(!root){
        root=++tot;
    }
    if(l==r){
        Max[root]=make_pair(Max[root].first+num,-pos);
        return;
    }
    int mid=(l+r)>>1;
    if(pos<=mid){
        insert(lc[root],l,mid,pos,num);
    }
    else{
        insert(rc[root],mid+1,r,pos,num);
    }
    Max[root]=max(Max[lc[root]],Max[rc[root]]);
}
int Merge(int x,int y,int l,int r){
    if(!x){
        return y;
    }
    if(!y){
        return x;
    }
    int mid=(l+r)>>1;
    if(l==r){
        Max[x].first+=Max[y].first;
        return x;
    }
    lc[x]=Merge(lc[x],lc[y],l,mid);
    rc[x]=Merge(rc[x],rc[y],mid+1,r);
    Max[x]=max(Max[lc[x]],Max[rc[x]]);
    return x;
}
void Dfs(int x){
    int i,k;
    for(i=Head[x];i;i=Next[i]){
        k=v[i];
        if(k!=fa[x][0]){
            Dfs(k);
            root[x]=Merge(root[x],root[k],1,M);
        }
    }
    ans[x]=-Max[root[x]].second;
}
int main(){
    int x,y,z;
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dep[1]=1;
    dfs(1);
    for(int i=1;i<=m;++i){
        scanf("%d%d%d",&x,&y,&z);
        insert(root[x],1,M,z,1);
        insert(root[y],1,M,z,1);
        insert(root[lca(x,y)],1,M,z,-1);
        insert(root[fa[lca(x,y)][0]],1,M,z,-1);
    }
    Dfs(1);
    for(int i=1;i<=n;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ukcxrtjr/p/11311643.html
今日推荐