• 最近公共祖先(LCA)(题目)


    Time Limit: 2000 ms Memory Limit: 256 MB

    Description

    Input

    Output

    Sample Input

    15 5
    1 2 3 4 5 6 7 8 9 10 11 12 13 14
    1 1 2 2 3 3 4 4 5 5 6 6 7 7
    1 2
    8 11
    5 8
    8 15
    4 6
    

    Sample Output

    1
    5
    4
    7
    3
    

    HINT


    Solution

      这题是为了放上来提醒一下自己主席树还能这么用的。。不然主席树真的都快荒废了(我这是多久没打这种题了。。。)

    ​  

      首先一句话题意的话就是:给你两棵树,找一个标号最大的点,满足这个点是(x)(A)树中祖先,也是(y)(B)树中的祖先

      因为有两棵树,我们要考虑两棵树共有的部分,所以可以从其中一棵树中的某些节点对另一棵树的贡献这样的角度来入手

      一个简单粗暴的想法,我们将询问离线,对于每个(A)树上的点记录有关这个点的询问

      然后在(A)树上dfs,然后每遍历到一个点,就把这个点对(B)树中点的贡献算上

      具体一点就是,假如当前遍历到点(u),我们考虑(u)这个点是(B)树中哪些点的祖先,然后用这些(u)来更新这些点记录的祖先最大值(存在某个东西里面,这个值初始的时候应该要继承父节点的数据),因为我们是按照dfs的顺序来算贡献的,所以可以保证到目前为止,用来更新(B)树中贡献的,都是(A)树上(u)到根路径上的点,也就是(u)所有的祖先,那么我们只要对于(u)点中的每个询问,查询一下对应的在(B)树中的那个点对应的最大值就好了

      然而我们要用什么东西来维护这个呢?

      发现(u)能更新的应该是(u)这个点在(B)树中的子树内的所有点,那可以用(dfs)序搞成一个区间修改,那很容易就想到线段树了,接着发现我们要继承父节点的数据,那直接主席树爆搞一波即可

      

      代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int MAXN=2*(1e5)+10,SEG=MAXN*20*2;
    struct xxx{
    	int y,nxt;
    }a[MAXN*4];
    struct Q{
    	int y,id;
    	Q(){}
    	Q(int _y,int _id){y=_y; id=_id;}
    };
    int h[MAXN],h1[MAXN],st[MAXN],lis[MAXN],ed[MAXN];
    int rt[MAXN],ans[MAXN];
    vector<Q> q[MAXN];
    namespace Seg{/*{{{*/
    	int ch[SEG][2],mx[SEG],tag[SEG];
    	int tot,n;
    	void init(int _n){n=_n;}
    	int newnode(int pre){
    		ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1];
    		mx[tot]=mx[pre]; tag[tot]=tag[pre];
    		return tot;
    	}
    	void pushup(int x){mx[x]=max(mx[ch[x][0]],mx[ch[x][1]]);}
    	void givetag(int x,int delta){mx[x]=max(mx[x],delta); tag[x]=max(tag[x],delta);}
    	void _update(int pre,int &x,int l,int r,int lx,int rx,int delta){
    		x=newnode(pre);
    		if (l<=lx&&rx<=r){
    			givetag(x,delta); return;
    		}
    		int mid=lx+rx>>1;
    		if (l<=mid) _update(ch[pre][0],ch[x][0],l,r,lx,mid,delta);
    		if (r>mid) _update(ch[pre][1],ch[x][1],l,r,mid+1,rx,delta);
    		pushup(x);
    	}
    	void update(int pre,int x,int l,int r,int delta){_update(rt[pre],rt[x],l,r,1,n,delta);}
    	int _query(int x,int d,int lx,int rx){
    		if (!x) return 0;
    		if (lx==rx) return mx[x];
    		int mid=lx+rx>>1,ret=0;
    		pushup(x);
    		if (d<=mid) return max(_query(ch[x][0],d,lx,mid),tag[x]);
    		else return max(_query(ch[x][1],d,mid+1,rx),tag[x]);
    	}
    	int query(int x,int d){return _query(rt[x],d,1,n);}
    }/*}}}*/
    int n,m,tot,t;
    void add(int x,int y,int *h);
    void dfs(int x);
    void dfs1(int fa,int x);
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x,y;
    	scanf("%d%d",&n,&m);
    	memset(h,-1,sizeof(h));
    	memset(h1,-1,sizeof(h1));
    	tot=0;
    	for (int i=2;i<=n;++i){
    		scanf("%d",&x);
    		add(x,i,h1);
    	}
    	for (int i=2;i<=n;++i){
    		scanf("%d",&x);
    		add(x,i,h);
    	}
    	for (int i=1;i<=m;++i){
    		scanf("%d%d",&x,&y);
    		q[x].push_back(Q(y,i));
    	}
    	Seg::init(n);
    	t=0;
    	dfs(1);
    	dfs1(0,1);
    	for (int i=1;i<=m;++i)
    		printf("%d
    ",ans[i]);
    }
    
    void add(int x,int y,int *h){
    	a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot; 
    }
    
    void dfs(int x){//B
    	int u;
    	st[x]=++t; lis[t]=x;
    	for (int i=h[x];i!=-1;i=a[i].nxt){
    		u=a[i].y;
    		dfs(u);
    	}
    	ed[x]=t;
    }
    
    void dfs1(int fa,int x){//A
    	Q tmp;
    	int u;
    	Seg::update(fa,x,st[x],ed[x],x);
    	for (int i=0;i<q[x].size();++i){
    		tmp=q[x][i];
    		ans[tmp.id]=Seg::query(x,st[tmp.y]);
    	}
    	for (int i=h1[x];i!=-1;i=a[i].nxt){
    		u=a[i].y;
    		dfs1(x,u);
    	}
    }
    
  • 相关阅读:
    springboot 过滤器中使用@Autowired 为空 以及 使用 @Value 无法读取yml配置的问题解决
    提示bash: telnet: command not found的解决方法
    java获取三个月之前时间与当前时间
    CentOS7 firewalld防火墙的常用命令
    SpringBoot项目连接Redis启动报错(Unable to validate object)
    【mac os 使用技巧】
    latex beamer标题过长不能放入标题框问题的解决
    一文了解.Net Core 3.1 Web API基础知识
    C# 使用RestSharp实现Postman中的各种形式的请求
    EntityFrameworkCore 3.0以上版本不支持sqlserver 2012以下版本分页的问题
  • 原文地址:https://www.cnblogs.com/yoyoball/p/8909908.html
Copyright © 2020-2023  润新知