• 最近公共祖先(lca)


     最近公共祖先(lca)

    题目描述

     

    给定一颗有n个结点的有根树,结点编号为1∼n,其中根结点为1号结点。每个结点都对应着一种颜色(黑/白)和一个固定的权值,初始时所有结点的颜色都为白色。现在你需要实现以下两种操作:

    ∙ Modify v∙ 将结点v的颜色修改成黑色;

    ∙ Query v∙ 找到一个黑色结点u,使得结点u和v的最近公共祖先z对应的权值尽可能的大,输出结点z的权值。如果此时树中不存在黑色结点,输出−1。

     

    输入

     

    第一行为两个正整数n和m,分别表示树中的结点数以及操作总数目。

    第二行为nn个正整数w1,w2,…,wn(wi≤109),分别表示这nn个结点对应的权值。

    接下来n−1行,每行两个正整数ai,bi表示结点ai和bi结点之间有一条边相连。

    接下来m行,每行由一个字符串str和一个正整数v组成,分别表示操作类型以及操作对应结点的编号。

     

    输出

     

    对于每个询问操作,每行输出一个整数,对应着这个询问的答案。

     

    样例输入

    7 7
    4 3 5 7 6 5 2
    1 4
    2 1
    7 5
    6 2
    2 5
    3 4
    Query 1
    Modify 2
    Modify 4
    Query 3
    Modify 2
    Modify 5
    Query 6

    样例输出

    -1
    7
    4

    提示

     

    对于10%10%的数据:n≤100,m≤200

    对于20%20%的数据:n≤3000,m≤3000

    对于另外20%20%的数据:对于编号为ii的结点,其父亲结点编号在[1,i−1]内均匀随机

    对于另外20%20%的数据:保证Query操作在所有Modify操作完成之后

    对于100%100%的数据:n≤105,m≤2×105

     

    来源

    ZYF&WMJ


    我的方法太傻逼,

    不建议参考!!!

    首先你发现,成为答案的点,一定在一个轻链顶端。

    于是我对于Modify,把它到根的路径加1 并把轻链的father的值加进线段树的Max里

    因为这些点有望成为lca。

    对于Query 

    假设我之前的链权值为111... (注意不是Max)

    然后跳了轻链后变成大于1的数,

    也就是说,有一个(多个)不同子树的染黑节点经过了这个lca

    那么这个lca就是合法的

    接着还要询问Max (相当于另一个染黑节点跳上了这条链)

    码量大,细节多

    调了一早上,成绩 :10 分

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 100005
    using namespace std;
    int n,m,head[maxn],son[maxn],size[maxn],deep[maxn],fa[maxn],top[maxn];
    int w[maxn],dfn[maxn],dy[maxn],sc,li,ri,tot,t1,t2,t,a,flag;
    int root,ans,la,mla;
    char cha[8];
    struct node{
        int v,nex;
    }e[maxn*2];
    struct no{
        int l,r,ma,y,x,bj;
    }tree[maxn*4];
    void lj(int t1,int t2){
        tot++;e[tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
    }
    void dfs1(int k,int fath){
        fa[k]=fath;deep[k]=deep[fath]+1;
        int gp=-1,sz=0;
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v!=fath){
                dfs1(e[i].v,k);
                if(gp==-1)gp=e[i].v;
                if(size[e[i].v]>size[gp])gp=e[i].v;
                sz+=size[e[i].v];
            }
        }
        son[k]=gp,size[k]=sz+1;
    }
    void dfs2(int k){
        dfn[k]=++sc;dy[sc]=k;
        if(son[k]!=-1)top[son[k]]=top[k],dfs2(son[k]);
        for(int i=head[k];i;i=e[i].nex){
            if(e[i].v!=fa[k]&&e[i].v!=son[k]){
                top[e[i].v]=e[i].v;
                dfs2(e[i].v);
            }
        }
    }
    void wh(int k){
        tree[k].x=max(tree[k*2].x,tree[k*2+1].x);
        tree[k].y=min(tree[k*2].y,tree[k*2+1].y);
        tree[k].ma=max(tree[k*2].ma,tree[k*2+1].ma);
    }
    void build(int k,int L,int R){
        tree[k].l=L,tree[k].r=R;
        if(L==R)return;
        int mid=L+R>>1;
        build(k*2,L,mid);build(k*2+1,mid+1,R);
        wh(k);
    }
    void down(int k){
        if(tree[k].bj>0){
            t=tree[k].bj;
            tree[k*2].x+=t;tree[k*2+1].x+=t;
            tree[k*2].y+=t;tree[k*2+1].y+=t;
            tree[k*2].bj+=t;tree[k*2+1].bj+=t;
            tree[k].bj=0;
        }
    }
    void ch(int k,int pl){
        if(tree[k].l==tree[k].r){
            tree[k].ma=w[dy[tree[k].l]];
            return;
        }
        down(k);
        int mid=tree[k].l+tree[k].r>>1;
        if(pl<=mid)ch(k*2,pl);
        else ch(k*2+1,pl);
        wh(k);
    }
    void jia(int k){
        if(tree[k].l>=li&&tree[k].r<=ri){
            tree[k].x++;tree[k].y++;tree[k].bj++;
            //cout<<tree[k].l<<' '<<tree[k].r<<' '<<tree[k].x<<' '<<tree[k].y<<endl;
            return;
        }
        down(k);
        int mid=tree[k].l+tree[k].r>>1;
        if(li<=mid)jia(k*2);
        if(ri>mid)jia(k*2+1);
        wh(k);
    }
    void ask_p(int k,int pl){
     
        if(tree[k].l==tree[k].r){
            if(tree[k].x>la){
                ans=max(ans,w[dy[tree[k].l]]);
                la=tree[k].x;
            }
            return;
        }
        down(k);
        int mid=tree[k].l+tree[k].r>>1;
        if(pl<=mid)ask_p(k*2,pl);
        else ask_p(k*2+1,pl);
    }
    void ask_l(int k){
         
        if(tree[k].l>=li&&tree[k].r<=ri){
        //cout<<"aa "<<tree[k].l<<' '<<tree[k].r<<endl;
            if(tree[k].x<=la)return;
            if(tree[k].y<=la){
            //cout<<la<<' '<<tree[k].x<<' '<<tree[k].y<<endl
                down(k);
                int ls=k*2,rs=k*2+1;
                if(tree[rs].x>la){
                    ans=max(ans,tree[ls].ma);mla=max(mla,tree[ls].x);
                     
                    ask_l(k*2+1);
                }
                else {
                    if(tree[ls].x<=la)return;
                    //down(k);
                    ask_l(k*2);
                }
                return;
            }
            ans=max(ans,tree[k].ma);mla=max(mla,tree[k].x);
            return;
        }
        down(k);
        int mid=tree[k].l+tree[k].r>>1;
        if(li<=mid)ask_l(k*2);
        if(ri>mid)ask_l(k*2+1);
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        for(int i=1;i<n;i++){
            scanf("%d%d",&t1,&t2);
            lj(t1,t2);lj(t2,t1);
        }
        dfs1(1,0);top[1]=1;dfs2(1);root=1;
        build(1,1,n);
        //for(int i=1;i<=n;i++)cout<<dfn[i]<<' ';cout<<endl; 
        for(int i=1;i<=m;i++){
            scanf("%s %d",cha,&a);
            if(cha[0]=='M'){
                flag=1;
                t1=top[a];
                while(t1!=root){
                    ch(1,dfn[a]);
                    li=dfn[t1],ri=dfn[a];
                    jia(1);
                    a=fa[t1];t1=top[a];
                     
                }//cout<<"aaa  "<<a<<' '<<dfn[a]<<endl;;
                ch(1,dfn[a]);
                li=dfn[root],ri=dfn[a];
                jia(1);
            }
            if(cha[0]=='Q'){
                if(!flag){puts("-1");continue;}
                t1=top[a];ans=0;la=0;
                while(t1!=root){
                    ask_p(1,dfn[a]);
                    //cout<<"aa "<<la<<endl;
                    li=dfn[t1],ri=dfn[a];
                    mla=0;/////
                    ask_l(1);//cout<<dfn[a]<<' '<<ans<<endl;
                    la=max(la,mla);//cout<<mla<<endl;
                    a=fa[t1],t1=top[a];
                }
                //cout<<"aaa "<<la<<endl;
                ask_p(1,dfn[a]);
                //cout<<dfn[a]<<' '<<ans<<endl;
                li=dfn[root],ri=dfn[a];
                mla=0;ask_l(1);la=max(la,mla);
                printf("%d
    ",ans);
            }
        }
        return 0;
    } 
     

     

  • 相关阅读:
    作业5

    Linux系统管理4
    作业
    递归训练1:在两个长度相等的排序数组中找到上中位数
    LeetCode:面试题 08.05. 递归乘法
    LeetCode:面试题 08.06. 汉诺塔问题
    LeetCode:22. 括号生成
    如何仅用递归函数和栈操作逆序一个栈
    LeetCode:面试题 03.02. 栈的最小值
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358844.html
Copyright © 2020-2023  润新知