最近公共祖先(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\n",ans);
        }
    }
    return 0;
} 
 

 

猜你喜欢

转载自blog.csdn.net/liankewei123456/article/details/82227062