前 言:

一直很想写这道括号树。。毕竟是在去年折磨了我4个小时的题。。。。

上午小测3 T1 括号序列

前言:

原来这题是个dp啊。。。这几天出了好几道dp,我都没看出来,我竟然折磨菜。

考试的时候先打了个暴力,然后就开始往容斥上想。。。。

解析:

考虑dp。

令dp[i] 表示以i为结尾的,合法的子串数量。

令match[i] 表示进行括号匹配时,与i匹配的括号的编号。

(以上i都是右括号,如果是左括号置为0即可)

然后,就有: if(match[i]) dp[i]=dp[match[i]-1]+1;

这个转移方程的含义如下:

首先是前面的判断语句。必须是在i有匹配的情况下。

这样就排除了两种不可能的情况,一种是i是左括号,另一种是i是右括号,但在进行括号匹配时,没有与其匹配的左括号。

显然以上两种情况,i都不可能成为一个合法字串的结尾。

然后是要先给dp[i]加上1。这是以match[i]为起点,i为终点的子串的贡献。

其次要加上dp[match[i]-1];

这时分两种情况讨论。

第一种是 s[match[i]-1]==')' : 好丑的图

此时以i为结尾的子串还可能继续向左延伸,只要加上dp[match[i]-1]即可。

另外一种是 s[match[i]-1]=='(':

此时不能继续向左延伸,所以不加,但是因为dp[match[i]-1]是0,所以加上也不会错(主要是这样写起来方便)

说的有些麻烦了,其实还是挺显然的。

代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000000+10;
#define gc() (p1 == p2 ? (p2 = buf + fread(p1 = buf, 1, 1 << 20, stdin), p1 == p2 ? EOF : *p1++) : *p1++)
#define read() ({ register int x = 0, f = 1; register char c = gc(); while(c < '0' || c > '9') { if (c == '-') f = -1; c = gc();} while(c >= '0' && c <= '9') x = x * 10 + (c & 15), c = gc(); f * x; })
char buf[1 << 20], *p1, *p2;
char s[maxn];
int n,top;
int dp[maxn];
int match[maxn];
ll ans;
struct node{
int pos;
char c;
node(){}
node(int x,char y){
pos=x;
c=y;
}
}Stack[maxn];
void Solve(){
scanf("%s",s+1);
n=strlen(s+1);
Stack[++top]=node(1,s[1]);
for(int i=2;i<=n;++i){
if(s[i]==')'&&Stack[top].c=='('){
node t=Stack[top];
top--;
match[i]=t.pos;
}else Stack[++top]=node(i,s[i]);
}
for(int i=1;i<=n;++i){
if(match[i]){
dp[i]=1+dp[match[i]-1];
}
}
for(int i=1;i<=n;++i) ans+=dp[i];
printf("%lld\n",ans);
}
int main(){
freopen("bracket.in","r",stdin);
freopen("bracket.out","w",stdout);
Solve();
return 0;
}

luogu P5658 [CSP/S 2019 D1T2] 括号树

前言:

其实应该不是很难吧。。。

解析:

和上一道题类似,但不是完全相同废话

所以一定要看清题啊。。。

这次问的是每个字符串的合法子串数量。。。我当成以每个字符结尾的合法字串数量了,直接暴毙。。。

会上面那道题,这个就简单多了。

先令dp[i]表示以i结尾的合法字子串数量,然后求个树上前缀和就行了。

照上个题的思路,改改式子:

if(match[i]) dp[i]=dp[fa[match[i]]]+1

最后。。。

不开long long见祖宗!

代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=500000+10;
#define gc() (p1 == p2 ? (p2 = buf + fread(p1 = buf, 1, 1 << 20, stdin), p1 == p2 ? EOF : *p1++) : *p1++)
#define read() ({ register int x = 0, f = 1; register char c = gc(); while(c < '0' || c > '9') { if (c == '-') f = -1; c = gc();} while(c >= '0' && c <= '9') x = x * 10 + (c & 15), c = gc(); f * x; })
char buf[1 << 20], *p1, *p2;
struct node{
int to,nxt;
}edge[maxn<<1];
int head[maxn],fa[maxn],match[maxn];
ll dp[maxn];
char s[maxn];
struct Node{
int pos;
char c;
Node(){}
Node(int x,char y){
pos=x;
c=y;
}
}Stack[maxn];
int n,cnt,top;
ll ans;
void add(int from,int to){
edge[++cnt].to=to;
edge[cnt].nxt=head[from];
head[from]=cnt;
}
void dfs1(int u){
Node t=Stack[top];
if(t.c=='('&&s[u]==')'){
match[u]=t.pos;
top--;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u]) continue;
dfs1(v);
}
Stack[++top]=Node(t.pos,t.c);
}else{
Stack[++top]=Node(u,s[u]);
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u]) continue;
dfs1(v);
}
top--;
}
}
void dfs2(int u){
if(match[u]) dp[u]=dp[fa[match[u]]]+1;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u]) continue;
dfs2(v);
}
}
void dfs3(int u,int f){
dp[u]+=dp[f];
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u]) continue;
dfs3(v,u);
}
}
void Solve(){
scanf("%d%s",&n,s+1);
for(int i=2;i<=n;++i){
scanf("%d",&fa[i]);
add(i,fa[i]);
add(fa[i],i);
}
dfs1(1);
dfs2(1);
dfs3(1,0);
for(int i=1;i<=n;++i) ans^=(1ll*i*dp[i]);
printf("%lld\n",ans);
}
int main(){
// freopen("brackets.in","r",stdin);
// freopen("brackets.out","w",stdout);
Solve();
return 0;
}

上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解的更多相关文章

  1. 上午小测1 T1 木板 题解

    前言: WTCL,居然折磨煎蛋的性质都忘记了,WTCL. 考场上想出来了正解,就差一点就能A掉,挺难受的. 要记住一个数n可能会有一个大于\(\sqrt{n}\)的质因子..我忘记把它加进去了.... ...

  2. CSP-S 2019 D1T2 括号树

    题目链接:[https://www.luogu.com.cn/problem/P5658] 思路: 这道题不难.(为什么我在考场上一点思路也没有??) 假设我们已经处理到树上的节点u(假设1为根节点) ...

  3. 上午小测1 B.序列 哈希表+数学

    题目描述 \(EZ\) 每周一都要举行升旗仪式,国旗班会站成一整列整齐地向前行进. 郭神摄像师想要选取其中一段照下来.他想让这一段中每个人的身高成等比数列,展示出最萌身高差.但他发现这个太难办到了.于 ...

  4. 括号序列模型--序列dp--U86873 小Y的精灵国机房之旅

    括号序列模型及解法 >Codeforces314E◦给定一个长度为n的仅包含左右括号和问号的字符串,将问号变成左括号或右括号使得该括号序列合法,求方案总数.◦例如(())与()()都是合法的括号 ...

  5. 学长小清新题表之UOJ 31.猪猪侠再战括号序列

    学长小清新题表之UOJ 31.猪猪侠再战括号序列 题目描述 大家好我是来自百度贴吧的_叫我猪猪侠,英文名叫\(\_CallMeGGBond\). 我不曾上过大学,但这不影响我对离散数学.复杂性分析等领 ...

  6. 2017-5-14 湘潭市赛 Parentheses 转化思想+贪心 使括号序列合法的最小花费。满足前面左括号的数量>=有括号的数量。

    Parentheses Accepted : Submit : Time Limit : MS Memory Limit : KB Parentheses Bobo has a very long s ...

  7. 括号序列(区间dp)

    括号序列(区间dp) 输入一个长度不超过100的,由"(",")","[",")"组成的序列,请添加尽量少的括号,得到一 ...

  8. 括号序列(Poj1141)

    Poj1141 题目描述: 定义合法的括号序列如下: 1 空序列是一个合法的序列 2 如果S是合法的序列,则(S)和[S]也是合法的序列 3 如果A和B是合法的序列,则AB也是合法的序列 例如:下面的 ...

  9. 括号序列的dp问题模型

    括号序列的dp问题模型 Codeforces314E ◦给定一个长度为n的仅包含左括号和问号的字符串,将问号变成左括号或 右括号使得该括号序列合法,求方案总数. ◦例如(())与()()都是合法的括号 ...

随机推荐

  1. Identity角色管理二(显示角色)

    需要将目前所有角色名显示出来,方法同用户管理 一.创建Index acction public async Task<ActionResult> Index() { var roles = ...

  2. [第十六篇]——Docker 安装 CentOS之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker 安装 CentOS CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise ...

  3. 数据结构与算法——平衡二叉树(AVL树)

    目录 二叉排序树存在的问题 基本介绍 单旋转(左旋转) 树高度计算 旋转 右旋转 双旋转 完整代码 二叉排序树存在的问题 一个数列 {1,2,3,4,5,6},创建一颗二叉排序树(BST) 创建完成的 ...

  4. 1004. 最大连续1的个数 III

    1004. 最大连续1的个数 III 给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 . 返回仅包含 1 的最长(连续)子数组的长度. 示例 1: 输入:A = ...

  5. linux停止进程

    $ kill -QUIT 主进程号 例如:kill -QUIT 1708 这种方式相对来说会有一个停止的过程,先将子进程停止掉,然后再停掉主进程. 快速停止Nginx: $ kill -TERM 主进 ...

  6. html回车键搜索内容

    window.onkeydown = function(e){ // elsinput是搜索框 if(e.keyCode === 13 && elsinput.is(':focus') ...

  7. redis 设置密码 laravel框架配置redis

    * 参考资料 redis文档             http://www.redis.cn/documentation.html,  http://redisdoc.com/index.html r ...

  8. 『PyTorch』屌丝的PyTorch玩法

    1. prefetch_generator 使用 prefetch_generator库 在后台加载下一batch的数据,原本PyTorch默认的DataLoader会创建一些worker线程来预读取 ...

  9. P4590-[TJOI2018]游园会【dp套dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P4590 题目大意 给出一个长度为\(m\)的字符串\(s\). 对于每个\(k\in[0,m]\)求有多少个长度为 ...

  10. 通用JS9

    Symbol.toStringTag 该符号作为一个属性表示"一个字符串,该字符串用于创建对象的默认字符串描述."由内置方法Object.prototype.toString()使 ...