zoukankan      html  css  js  c++  java
  • CF600E Lomsat gelral【题解】线段树合并

    Luogu题目:https://www.luogu.com.cn/problem/CF600E

    值域线段树加合并。

    基本上就是裸的。

    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int maxn=1e5+10;
    int c[maxn],n,cnt;
    struct node{
        int nxt,to;
        #define nxt(x) e[x].nxt
        #define to(x) e[x].to
    }e[maxn<<1];
    int head[maxn],tot,rt[maxn],ans[maxn];
    inline void add(int from,int to){
        to(++tot)=to;
        nxt(tot)=head[from];head[from]=tot;
    }
    struct tree{
        int lc,rc,tg,dt;
    }t[maxn*50];
    inline void pushup(int p){
        t[p].dt=max(t[t[p].lc].dt,t[t[p].rc].dt);
        if(t[t[p].lc].dt==t[t[p].rc].dt) t[p].tg=t[t[p].lc].tg+t[t[p].rc].tg;
        else t[p].tg= t[t[p].lc].dt > t[t[p].rc].dt ? t[t[p].lc].tg : t[t[p].rc].tg;
    }
    inline 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=l;
            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);
        pushup(p);
        return p;
    }
    void change(int &p,int l,int r,int wh){
        if(!p) p=++cnt;
        if(l==r){
            t[p].dt+=1;t[p].tg=wh;return;
        }
        int mid=(l+r)>>1;
        if(wh<=mid) change(t[p].lc,l,mid,wh);
        else change(t[p].rc,mid+1,r,wh);
        pushup(p);
    }
    int dfs(int now,int fa){
        for(int i=head[now];i;i=nxt(i)){
            int to=to(i);
            if(to==fa) continue;
            dfs(to,now);
            rt[now]=merge(rt[now],rt[to],1,maxn);
        }
        change(rt[now],1,maxn,c[now]);
        ans[now]=t[rt[now]].tg;
    }
    signed main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&c[i]),rt[i]=++cnt;
        for(int i=1;i<n;i++){
            int x,y;scanf("%lld%lld",&x,&y);
            add(x,y);add(y,x);
        }
        dfs(1,0);
        for(int i=1;i<=n;i++)
            printf("%lld ",ans[i]);
        return 0;
    }
  • 相关阅读:
    Redis简介 安装 注册服务
    Supervisor Linux守护进程
    .Net5 控制台 读取配置文件+依赖注入
    Linux Gdip
    Net Core封装 踩坑
    Apollo 公共Namespace使用json
    Visual Studio 2019修改项目名
    【面向对象】--静态类与非静态类的区别
    win10设置默认中英文符号【程序员标配】
    MySQL 数据库访问驱动-版本问题
  • 原文地址:https://www.cnblogs.com/ChrisKKK/p/11544632.html
Copyright © 2011-2022 走看看