上午小测3 T1 括号序列 && luogu P5658 [CSP/S 2019 D1T2] 括号树 题解
前 言:
一直很想写这道括号树。。毕竟是在去年折磨了我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 T1 木板 题解
前言: WTCL,居然折磨煎蛋的性质都忘记了,WTCL. 考场上想出来了正解,就差一点就能A掉,挺难受的. 要记住一个数n可能会有一个大于\(\sqrt{n}\)的质因子..我忘记把它加进去了.... ...
- CSP-S 2019 D1T2 括号树
题目链接:[https://www.luogu.com.cn/problem/P5658] 思路: 这道题不难.(为什么我在考场上一点思路也没有??) 假设我们已经处理到树上的节点u(假设1为根节点) ...
- 上午小测1 B.序列 哈希表+数学
题目描述 \(EZ\) 每周一都要举行升旗仪式,国旗班会站成一整列整齐地向前行进. 郭神摄像师想要选取其中一段照下来.他想让这一段中每个人的身高成等比数列,展示出最萌身高差.但他发现这个太难办到了.于 ...
- 括号序列模型--序列dp--U86873 小Y的精灵国机房之旅
括号序列模型及解法 >Codeforces314E◦给定一个长度为n的仅包含左右括号和问号的字符串,将问号变成左括号或右括号使得该括号序列合法,求方案总数.◦例如(())与()()都是合法的括号 ...
- 学长小清新题表之UOJ 31.猪猪侠再战括号序列
学长小清新题表之UOJ 31.猪猪侠再战括号序列 题目描述 大家好我是来自百度贴吧的_叫我猪猪侠,英文名叫\(\_CallMeGGBond\). 我不曾上过大学,但这不影响我对离散数学.复杂性分析等领 ...
- 2017-5-14 湘潭市赛 Parentheses 转化思想+贪心 使括号序列合法的最小花费。满足前面左括号的数量>=有括号的数量。
Parentheses Accepted : Submit : Time Limit : MS Memory Limit : KB Parentheses Bobo has a very long s ...
- 括号序列(区间dp)
括号序列(区间dp) 输入一个长度不超过100的,由"(",")","[",")"组成的序列,请添加尽量少的括号,得到一 ...
- 括号序列(Poj1141)
Poj1141 题目描述: 定义合法的括号序列如下: 1 空序列是一个合法的序列 2 如果S是合法的序列,则(S)和[S]也是合法的序列 3 如果A和B是合法的序列,则AB也是合法的序列 例如:下面的 ...
- 括号序列的dp问题模型
括号序列的dp问题模型 Codeforces314E ◦给定一个长度为n的仅包含左括号和问号的字符串,将问号变成左括号或 右括号使得该括号序列合法,求方案总数. ◦例如(())与()()都是合法的括号 ...
随机推荐
- Identity角色管理二(显示角色)
需要将目前所有角色名显示出来,方法同用户管理 一.创建Index acction public async Task<ActionResult> Index() { var roles = ...
- [第十六篇]——Docker 安装 CentOS之Spring Cloud直播商城 b2b2c电子商务技术总结
Docker 安装 CentOS CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise ...
- 数据结构与算法——平衡二叉树(AVL树)
目录 二叉排序树存在的问题 基本介绍 单旋转(左旋转) 树高度计算 旋转 右旋转 双旋转 完整代码 二叉排序树存在的问题 一个数列 {1,2,3,4,5,6},创建一颗二叉排序树(BST) 创建完成的 ...
- 1004. 最大连续1的个数 III
1004. 最大连续1的个数 III 给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 . 返回仅包含 1 的最长(连续)子数组的长度. 示例 1: 输入:A = ...
- linux停止进程
$ kill -QUIT 主进程号 例如:kill -QUIT 1708 这种方式相对来说会有一个停止的过程,先将子进程停止掉,然后再停掉主进程. 快速停止Nginx: $ kill -TERM 主进 ...
- html回车键搜索内容
window.onkeydown = function(e){ // elsinput是搜索框 if(e.keyCode === 13 && elsinput.is(':focus') ...
- redis 设置密码 laravel框架配置redis
* 参考资料 redis文档 http://www.redis.cn/documentation.html, http://redisdoc.com/index.html r ...
- 『PyTorch』屌丝的PyTorch玩法
1. prefetch_generator 使用 prefetch_generator库 在后台加载下一batch的数据,原本PyTorch默认的DataLoader会创建一些worker线程来预读取 ...
- P4590-[TJOI2018]游园会【dp套dp】
正题 题目链接:https://www.luogu.com.cn/problem/P4590 题目大意 给出一个长度为\(m\)的字符串\(s\). 对于每个\(k\in[0,m]\)求有多少个长度为 ...
- 通用JS9
Symbol.toStringTag 该符号作为一个属性表示"一个字符串,该字符串用于创建对象的默认字符串描述."由内置方法Object.prototype.toString()使 ...