牛客国庆集训派对Day6 I - 树链剖分

版权声明:欢迎随便转载。 https://blog.csdn.net/a1214034447/article/details/82988982

题目链接:点击这里

解题思路;

懒人标记树链剖分更新区间最大值,然后每次查询区间内最大值有等于K的,之后改为-inf.

时间复杂度O(n*logn*logn)

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mx = 1e5 + 10;
int num[mx],n,head[mx],tot,fa[mx];
int siz[mx],dep[mx],size,top[mx];
int L,R,m,K,ans[mx];
int add[mx<<2],Max[mx<<2];
int a[mx],b[mx],c[mx];
struct node 
{ 
    int son,nxt;    
}Edge[mx<<1]; 
void AddEdge(int x,int y) 
{ 
    Edge[tot].son = y; 
    Edge[tot].nxt = head[x]; 
    head[x] = tot++; 
} 
void dfs1(int x,int f)//求重儿子,深度,树大小等等
{
    dep[x] = dep[f] + 1;
    siz[x] = 1;
    int p = 0,wei = 0;
    for(int i=head[x];~i;i=Edge[i].nxt)
    {
        int son = Edge[i].son;
        if(son==f) continue;
        fa[son] = x;
        dfs1(son,x);
        siz[x] += siz[son];
        if(siz[son]>siz[wei]) wei = son,p = i;
    }
    //把重儿子换到第一个
    if(p) swap(Edge[head[x]].son,Edge[p].son);
}
void dfs2(int x,int f)//重链轻链编号
{
    num[x] = ++size;
    for(int i=head[x];~i;i=Edge[i].nxt)
    {
        int son = Edge[i].son;
        if(son==f) continue;
        if(i==head[x]) top[son] = top[x];//是不是重儿子
        else top[son] = son;
        dfs2(son,x);
    }
}
void push_up(int rt)
{
    Max[rt<<1] += add[rt];
    Max[rt<<1|1] += add[rt];
    add[rt<<1] += add[rt];
    add[rt<<1|1] += add[rt];
    add[rt] = 0;
}
void update(int l,int r,int rt)
{
    if(L<=l&&r<=R){
        add[rt]++;
        Max[rt]++;
        return ;
    }
    push_up(rt);
    int mid = (l+r)>>1;
    if(L<=mid) update(lson);
    if(R>mid) update(rson);
    Max[rt] = max(Max[rt<<1],Max[rt<<1|1]);
}
void mask(int x,int y)
{
    int f1 = top[x],f2 = top[y];
    while(f1!=f2){
        if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
        L = num[f1],R = num[x];
        x = fa[f1],f1 = top[x];
        update(1,n,1);
    }
    L = min(num[x],num[y]);
    R = max(num[x],num[y]);
    update(1,n,1); 
}
void check(int l,int r,int rt,int cr)
{
    if(Max[rt]<K) return ;
    if(l==r){
        ans[l] = cr;
        Max[rt] = -inf;
        return ;
    }
    push_up(rt);
    int mid = (l+r)>>1;
    check(lson,cr);check(rson,cr);
    Max[rt] = max(Max[rt<<1],Max[rt<<1|1]);
}
int main()
{
    scanf("%d%d%d",&n,&m,&K);
    memset(head,-1,sizeof(head));
    int u,v;
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        AddEdge(u,v);
        AddEdge(v,u);
    }
    for(int i=1;i<=m;i++) scanf("%d%d%d",a+i,b+i,c+i);
    dfs1(1,0),dfs2(1,0);
    for(int i=m;i>=1;i--){
        mask(a[i],b[i]);
        check(1,n,1,c[i]);
    }
    for(int i=1;i<=n;i++) printf("%d%c",ans[num[i]],i==n?'\n':' ');
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/82988982