• 题解 P4810 【[COCI 2014/2015 #3]STOGOVI】


    题目链接

    Solution [COCI 2014/2015 #3]STOGOVI

    题目大意:维护一个可持久化栈,支持(push)(pop),以及比较两个版本栈相同元素个数。注意:(push)操作仅会(push)当前操作编号进栈。

    可持久化数据结构


    分析:

    暴力做法,(bitset),期望得分(0)(没有写,开小点应该有点分数)

    暴力做法的优化,可持久化权值线段树,每次比较相同元素个数,如果走到同一个节点就剪枝,在loj上面获得了53pts

    继续可持久化的思路,我也不知道我为啥当时想不开拿权值线段树去维护一个栈,我们把栈表示成一条链

    由于一个点如果被(pop)出去之后就不可能再被(push)进来了,所以两个栈元素交集一定是两个栈的公共前缀。两条链的公共前缀,和( ext{LCA})比较相似,因此我们在树上完成这个问题。

    (push)操作,直接新建一个点。(pop)操作,跳到它的父亲。比较操作,找到两个版本的链的结尾节点,取( ext{LCA})的深度就是答案。

    倍增可以维护

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int maxn = 3e5 + 100,maxdep = 25;
    vector<int> G[maxn];
    int faz[maxn][maxdep + 1],dep[maxn],pos[maxn],tot,n;
    inline void addedge(int from,int to){
    	G[from].push_back(to);
    	dep[to] = dep[from] + 1;
    	faz[to][0] = from;
    	for(int i = 1;i <= maxdep;i++)faz[to][i] = faz[faz[to][i - 1]][i - 1];
    }
    inline int lca(int x,int y){
    	if(dep[x] < dep[y])swap(x,y);
    	for(int i = maxdep;i >= 0;i--)
    		if(dep[faz[x][i]] >= dep[y])x = faz[x][i];
    	if(x == y)return x;
    	for(int i = maxdep;i >= 0;i--)
    		if(faz[x][i] != faz[y][i])x = faz[x][i],y = faz[y][i];
    	return faz[x][0];
    }
    char com[4];
    int main(){
    	scanf("%d",&n);
    	dep[0] = 1;
    	for(int v,w,i = 1;i <= n;i++){
    		scanf("%s %d",com,&v);
    		if(com[0] == 'a')addedge(pos[v],i),pos[i] = i;
    		else if(com[0] == 'b')printf("%d
    ",pos[v]),pos[i] = faz[pos[v]][0];
    		else if(com[0] == 'c')scanf("%d",&w),pos[i] = pos[v],printf("%d
    ",dep[lca(pos[v],pos[w])] - 1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    history对象
    排序算法总结
    Boltzmann机
    Sort Colors
    First Missing Positive
    Sort List
    Insertion Sort List
    Merge Two Sorted Lists
    Merge Sorted Array
    Sum Root to Leaf Numbers
  • 原文地址:https://www.cnblogs.com/colazcy/p/13641780.html
Copyright © 2020-2023  润新知