• luogu_P4092 [HEOI2016/TJOI2016]树


    https://www.luogu.org/problem/P4092

    给定一颗有根树,根为 11,有以下两种操作:

    1. 标记操作:对某个结点打上标记。(在最开始,只有结点 11 有标记,其他结点均无标记,而且对于某个结点,可以打多次标记。)

    2. 询问操作:询问某个结点最近的一个打了标记的祖先。(这个结点本身也算自己的祖先)

    你能帮帮她吗?

    输入格式

    第一行两个正整数 N 和 Q 分别表示节点个数和操作次数。

    接下来 N-1 行,每行两个正整数 u,v(1u,vn) 表示 u 到 v 有一条有向边。

    接下来 Q 行,形如 oper num ,oper 为 C 时表示这是一个标记操作, oper 为 Q 时表示这是一个询问操作。


    dfs序上搞线段树就行

    线段树维护两个值

    一个值表示每个点的深度最大的祖先(也就是最近祖先)用于维护更新,一个表示点编号,用于输出答案

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    
    #define ri register int
    #define u int
    #define NN 100005
    
    namespace fast {
    
        inline u in() {
            u x(0),f(1);
            char s=getchar();
            while(s<'0'||s>'9') {
                if(s=='-') {
                    f=-1;
                }
                s=getchar();
            }
            while(s>='0'&&s<='9') {
                x=(x<<1)+(x<<3)+s-'0';
                s=getchar();
            }
            return x*f;
        }
    
    }
    
    using fast::in;
    using std::max;
    
    namespace xds {
    
        u a[NN<<2],ans[NN<<2],aaa[NN<<2],add[NN<<2],sum[NN<<2];
    
        void build(const u &rt,const u &l,const u &r) {
            if(l==r) {
                sum[rt]=ans[rt]=a[l]=1;
                return;
            }
            u mid=(l+r)>>1;
            build(rt<<1,l,mid);
            build(rt<<1|1,mid+1,r);
            sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
        }
    
        void pushdown(const u &rt,const u &l,const u &r) {
            if(!add[rt]) return;
            u xrt=rt<<1;
            u mid=(r+l)>>1;
            if(sum[xrt]<add[rt]) {
                sum[xrt]=add[rt];
                ans[xrt]=aaa[rt];
            }
            if(sum[xrt|1]<add[rt]) {
                sum[xrt|1]=add[rt];
                ans[xrt|1]=aaa[rt];
            }
            if(add[xrt]<add[rt]) {
                add[xrt]=add[rt];
                aaa[xrt]=aaa[rt];
            }
            if(add[xrt|1]<add[rt]) {
                add[xrt|1]=add[rt];
                aaa[xrt|1]=aaa[rt];
            }
            add[rt]=aaa[rt]=0;
        }
    
        void update(const u &rt,const u &l,const u &r,const u &x,const u &y,const u &v,const u &p) {
            if(x<=l&&y>=r) {
                if(sum[rt]<v) {
                    sum[rt]=v;
                    ans[rt]=p;
                }
                if(add[rt]<v) {
                    add[rt]=v;
                    aaa[rt]=p;
                }
                return;
            }
            pushdown(rt,l,r);
            u mid=(l+r)>>1;
            if(x<=mid) {
                update(rt<<1,l,mid,x,y,v,p);
            }
            if(mid<y) {
                update(rt<<1|1,mid+1,r,x,y,v,p);
            }
            sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
        }
    
        u query(const u &rt,const u &l,const u &r,const u &x) {
            if(l==r) {
                return ans[rt];
            }
            pushdown(rt,l,r);
            u mid=(r+l)>>1,re(0);
            if(x<=mid) {
                re=query(rt<<1,l,mid,x);
            } else {
                re=query(rt<<1|1,mid+1,r,x);
            }
            return re;
        }
    
    }
    
    namespace all {
    
        u N,Q,n;
    
        u h[NN],d[NN],cnt;
    
        struct node {
            u to,next;
        } a[NN<<1];
    
        struct point {
            u l,r;
        } p[NN];
    
        inline void add(const u &x,const u &y) {
            a[++cnt].to=y,a[cnt].next=h[x],h[x]=+cnt;
        }
    
        u dfs(const u &x,const u &prt,const u &deep) {
            p[x].l=++n,d[x]=deep;
            for(ri i(h[x]); i; i=a[i].next) {
                u _y(a[i].to);
                if(_y^prt) {
                    p[x].r=std::max(p[x].r,dfs(_y,x,deep+1));
                }
            }
            if(!p[x].r) p[x].r=p[x].l;
            return p[x].r;
        }
    
        inline void solve() {
            N=in(),Q=in();
            xds::build(1,1,N);
            for(ri i(1); i<N; ++i) {
                u _a(in()),_b(in());
                add(_a,_b),add(_b,_a);
            }
            dfs(1,0,1);
            for(ri i(1); i<=Q; ++i) {
                char _s(getchar());
                while(_s!='Q'&_s!='C')_s=getchar();
                u _x(in());
                if(_s=='Q') {
                    printf("%d
    ",xds::query(1,1,N,p[_x].l));
                } else {
                    xds::update(1,1,N,p[_x].l,p[_x].r,d[_x],_x);
                }
            }
        }
    
    }
    
    int main() {
    
        //freopen("4551.in","r",stdin);
        //freopen("4551.out","w",stdout);
        all::solve();
    
    }
  • 相关阅读:
    CPU被挖矿,Redis竟是内鬼!
    图解四种 IO 模型
    用户态和内核态的区别是啥
    关于 RocketMQ ClientID 相同引发的消息堆积的问题
    玩转 ByteBuffer
    RocketMQ Consumer 启动时都干了些啥?
    网络协议之:基于UDP的高速数据传输协议UDT
    dart系列之:安全看我,dart中的安全特性null safety
    JetBrains又出神器啦!Fleet,体验飞一般的感觉
    网络协议之:还在用HTTP代理?弱爆了!快试试SOCKS5
  • 原文地址:https://www.cnblogs.com/ling-zhi/p/11736780.html
Copyright © 2020-2023  润新知