• BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树


    BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树

    Description

    在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下
    两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个
    结点,可以打多次标记。)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖
    先)你能帮帮他吗?

    Input

    输入第一行两个正整数N和Q分别表示节点个数和操作次数接下来N-1行,每行两个正整数u,v(1≤u,v≤n)表示u到v
    有一条有向边接下来Q行,形如“opernum”oper为“C”时表示这是一个标记操作,oper为“Q”时表示这是一个询
    问操作对于每次询问操作,1 ≤ N, Q ≤ 100000。

    Output

    输出一个正整数,表示结果

    Sample Input

    5 5
    1 2

    1 3
    2 4
    2 5
    Q 2
    C 2
    Q 2
    Q 5
    Q 3

    Sample Output

    1
    2
    2
    1
     

    标记的时候直接标该点在dfs序中的位置。
    然后查询时查从根到这个点路径上点权最大值。
    因为dfs序的性质,可以保证最大的一定离这个点最近。
    然后树剖+线段树搞搞。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 200050
    #define ls p<<1
    #define rs p<<1|1
    int c[N<<2],a[N],n,m,dep[N],fa[N],son[N],idx[N],top[N];
    int head[N],to[N<<1],nxt[N<<1],cnt,siz[N],tot,sec,d[N];
    char opt[10];
    inline void add(int u,int v) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    }
    void dfs1(int x,int y) {
        a[x]=++sec;
        d[sec]=x;
        dep[x]=dep[y]+1;
        fa[x]=y;
        siz[x]=1;
        int i;
        for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
            dfs1(to[i],x);
            siz[x]+=siz[to[i]];
            if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
        }
    }
    void dfs2(int x,int t) {
        top[x]=t; idx[x]=++tot;
        int i;
        if(son[x]) dfs2(son[x],t);
        for(i=head[x];i;i=nxt[i]) if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
    }
    void update(int l,int r,int x,int v,int p) {
        if(l==r) {
            c[p]=v; return ;
        }
        int mid=(l+r)>>1;
        if(x<=mid) update(l,mid,x,v,ls);
        else update(mid+1,r,x,v,rs);
        c[p]=max(c[ls],c[rs]);
    }
    int qmx(int l,int r,int x,int y,int p) {
        if(x<=l&&y>=r) return c[p];
        int mid=(l+r)>>1,re=0;
        if(x<=mid) re=max(re,qmx(l,mid,x,y,ls));
        if(y>mid) re=max(re,qmx(mid+1,r,x,y,rs));
        return re;
    }
    int main() {
        scanf("%d%d",&n,&m);
        int i,x,y;
        for(i=1;i<n;i++) {
            scanf("%d%d",&x,&y);
            add(x,y);add(y,x);
        }
        dfs1(1,0);
        dfs2(1,1);
        update(1,n,idx[1],1,1);
        while(m--) {
            scanf("%s%d",opt,&x);
            if(opt[0]=='Q') {
                y=1;
                int ans=0;
                while(top[x]!=top[y]) {
                    if(dep[top[x]]>dep[top[y]]) swap(x,y);
                    ans=max(ans,qmx(1,n,idx[top[y]],idx[y],1));
                    y=fa[top[y]];
                }
                if(dep[x]<dep[y]) swap(x,y);
                ans=max(ans,qmx(1,n,idx[y],idx[x],1));
                printf("%d
    ",d[ans]);
            }else {
                update(1,n,idx[x],a[x],1);
            }
        }
    }
    
    
  • 相关阅读:
    129. Sum Root to Leaf Numbers
    113. Path Sum II
    114. Flatten Binary Tree to Linked List
    112. Path Sum
    100. Same Tree
    300. Longest Increasing Subsequence
    72. Edit Distance
    自定义js标签库
    JS 实现Table相同行的单元格自动合并示例代码
    mysql 高版本only_full_group_by 错误
  • 原文地址:https://www.cnblogs.com/suika/p/8742652.html
Copyright © 2020-2023  润新知