zoukankan      html  css  js  c++  java
  • [被踩计划] 题解 括号树

    为什么叫被踩记录呢?因为感觉自己之前真的是太菜了,打算把之前联赛等考过的题目做一做,看看自已以前有多菜,所以取名叫被踩记录。

    题目链接

    题目分析

    先考虑在一个序列上面做,然后再扩展到树上。

    首先,我们先计算以每个位置作为结尾的合法字串个数,然后再通过后缀和统计答案。

    如何求以某个位置作为结尾的合法字串个数?我们可以对每个位置找到长度最短的一个合法后缀,然后就转化成了一个子问题,可以用dp做了。

    举个例子:对于括号序列)())()(()),以最后一个位置作为结尾的合法后缀就是括号序列)())()以最后一个位置作为结尾的合法后缀数量加一,因为)())()(())=)())()+(()),而(())是一个合法括号串。

    如何求出这个长度最短的一个合法后缀?可以用栈来解决这个问题,栈中维护的大概是这样一个序列))...))((...((,同时维护栈中每个括号对应的位置,再分类讨论一下就行了,每次操作都是 (mathcal O(1)) 的。

    扩展到树上,做法还是一样的,可以再dfs的同时顺便维护栈,只要回退的时候恢复就行了。

    当然也可以不用dfs,考虑到每次弹栈然后入栈类似一个树的结构,所以只需要维护在这个“栈树”上的父亲即可实现弹栈和入栈了。

    参考代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=500005;
    char s[maxn];
    int pa[maxn],top[maxn],fa[maxn];
    long long cnt[maxn];
    int main(){
    	int n;
    	scanf("%d%s",&n,s+1);
    	pa[1]=0,top[1]=1;
    	for(int i=2;i<=n;++i){
    		int f;scanf("%d",&f);fa[i]=f;
    		if(s[i]=='('||!top[f]||s[top[f]]==')')
    			pa[top[i]=i]=top[f];
    		else
    			top[i]=pa[top[f]],cnt[i]=cnt[fa[top[f]]]+1;
    	}
    	for(int i=2;i<=n;++i)cnt[i]+=cnt[fa[i]];
    	long long ans=0;
    	for(int i=1;i<=n;++i)ans^=cnt[i]*i;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    解决ListView异步加载数据之后不能点击的问题
    android点击实现图片放大缩小 java技术博客
    关于 数据文件自增长 的一点理解
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Linux 超级用户的权利
    RAC 实例 迁移到 单实例 使用导出导入
    Shell 基本语法
    Linux 开机引导与关机过程
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Oracle RAC + Data Guard 环境搭建
  • 原文地址:https://www.cnblogs.com/lsq147/p/13746329.html
Copyright © 2011-2022 走看看