1. 1.      括号匹配

 

有一棵树,每个节点上都有一个括号(左括号或者右括号)。有多少个有序点对(u, v)从u到v的路径上的节点构成的字符串是一个合法的括号匹配?(我们称这样的点对是合法的)

输入格式

第一行是一个整数n,表示节点个数

第二行是一个字符串,由(和)组成,第i个字符表示第i个节点的括号。

接下来n-1行,每行两个整数u, v 表示u与v之间有一条边。

输出格式

输出一个整数,合法的点对数量。

输入样例

输出样例

4

()()

1 2

2 3

3 4

4

数据范围和约定

30%的数据:n <= 2000

100%的数据:n <= 100000

困扰了我多年(其实是多个月),终于于今日解决了!(我才不会说克罗地亚国赛最后一题是原题呢= =)如果没做过树分治的话还是先做一下poj1741感受一下叭。

先把随题配送的题解贴出来:

“这道题是很常规的树分治算法。分治之后考虑经过根的所有链,将链上的所有能匹配的括号合并,那么只有其中一边由若干左括号和另外一边的若干右括号的情况能构成合法的括号匹配。统计括号数即可。”

写的非常简洁,然而最初根本看不懂。事实上是这样子的,首先考虑当前子树,一条合法的括号序列链可以经过该子树的根节点,也可以不经过,对于后者可以递归求解,重点是看前者。

一条链经过这个根节点,那么这条链一定是长成这个样子的:

根

/ \

/     \

/         \

/             \

姑且把根旁边的两条支叫做左支与右支(注意原树并不一定是二叉树),那么这个括号序列一定是由左支的一些已经匹配好的括号序列,与右支的一些已经匹配好的括号序列,与左支还未匹配的 '(' 与右支未匹配的 ')' 。当然也有可能是由左支的一些已经匹配好的括号序列,与右支的一些已经匹配好的括号序列,与右支还未匹配的 '(' 与左支未匹配的 ')' 。这里不妨考虑前者。现在关键就是让那些分在两支的未匹配的括号得以匹配。具体的话还是看代码,最关键的是get_data()函数。还需要小注意一下78行的注释内容。

#include <cstdio>
#include <cstring>
#include <algorithm> const int maxn = 100005, LEFT = 0, RIGHT = 1; int n, head[maxn], to[maxn << 1], next[maxn << 1], lb, a[maxn], mp[128];
int t1, t2, siz[maxn], cnt[2][maxn], avail_len[2][maxn], idx[2], sum[2][maxn];
long long ans;
char ch, book[maxn]; inline void ist(int aa, int ss) {
to[lb] = ss;
next[lb] = head[aa];
head[aa] = lb;
++lb;
}
void get_siz(int r, int p) {
siz[r] = 1;
for (int j = head[r]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
get_siz(to[j], r);
siz[r] += siz[to[j]];
}
}
}
void fnd_zx(int r, int tot_node, int p, int & real_r, int & mn) {
int mx = 0;
for (int j = head[r]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
fnd_zx(to[j], tot_node, r, real_r, mn);
mx = std::max(mx, siz[to[j]]);
}
}
mx = std::max(mx, tot_node - siz[r]);
if (mn > mx) {
mn = mx;
real_r = r;
}
}
void get_data(int r, int p, int dir, int avail, int s) {
// r是当前子树的根节点,p是其父亲,dir是你想要找的可供与另一支匹配的括号类型,
// avail表示目前可供匹配的个数,s有点玄 ,只有当s为零的时候,这个括号序列才是
// 可以用来与另一支匹配的,用语言不好表达,简单模拟一下程序的45~61行就懂了
if (a[r] == dir) {
if (s) {
--s;
}
else {
++avail;
}
}
else {
++s;
}
if (!s) {
if (!cnt[dir][avail]) {
avail_len[dir][idx[dir]++] = avail;
}
++cnt[dir][avail];
}
for (int j = head[r]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
get_data(to[j], r, dir, avail, s);
}
}
}
void slove(int fake_r) {
int real_r = -666, mn = 2147483647, tem;
get_siz(fake_r, 0);
fnd_zx(fake_r, siz[fake_r], 0, real_r, mn);
book[real_r] = 1;
for (int j = head[real_r]; j != -1; j = next[j]) {
if (!book[to[j]]) {
slove(to[j]);
}
}
int mx_avail = 1; // mx_avail must be initialized to 1! 0 is NOT OK!
for (int j = head[real_r]; j != -1; j = next[j]) {
if (!book[to[j]]) {
if (a[real_r] == LEFT) {
get_data(to[j], real_r, LEFT, 1, 0);
get_data(to[j], real_r, RIGHT, 0, 0);
}
else {
get_data(to[j], real_r, RIGHT, 1, 0);
get_data(to[j], real_r, LEFT, 0, 0);
}
for (int dir = 0; dir < 2; ++dir) {
for (int k = 0; k < idx[dir]; ++k) {
tem = avail_len[dir][k];
mx_avail = std::max(mx_avail, tem);
ans -= (long long)cnt[dir][tem] * cnt[dir ^ 1][tem];
sum[dir][tem] += cnt[dir][tem];
cnt[dir][tem] = 0;
}
idx[dir] = 0;
}
}
} ++sum[a[real_r]][1];
for (int i = 0; i <= mx_avail; ++i) {
ans += (long long)sum[0][i] * sum[1][i];
sum[0][i] = 0;
sum[1][i] = 0;
} book[real_r] = 0;
} int main(void) {
freopen("bracket.in", "r", stdin);
freopen("bracket.out", "w", stdout);
memset(head, -1, sizeof head);
memset(next, -1, sizeof next);
mp['('] = LEFT;
mp[')'] = RIGHT;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
while ((ch = getchar()) < '(');
a[i] = mp[(int)ch];
}
for (int i = 1; i < n; ++i) {
scanf("%d%d", &t1, &t2);
ist(t1, t2);
ist(t2, t1);
} slove(1);
printf("%I64d\n", ans);
return 0;
}

  

[ZPG TEST 114] 括号匹配【树分治 点分治 括号序列】的更多相关文章

  1. C. Serval and Parenthesis Sequence 【括号匹配】 Codeforces Round #551 (Div. 2)

    冲鸭,去刷题:http://codeforces.com/contest/1153/problem/C C. Serval and Parenthesis Sequence time limit pe ...

  2. CF308C-Sereja and Brackets-(线段树+括号匹配)

    题意:给出一段括号,多次询问某个区间内能匹配多少括号. 题解:线段树,结构体三个属性,多余的左括号l,多余的右括号r,能够匹配的括号数val. 当前结点的val=左儿子的val+右儿子的val+min ...

  3. Sereja and Brackets(括号匹配)

    Description Sereja has a bracket sequence s1, s2, ..., sn, or, in other words, a string s of length  ...

  4. POJ1741——Tree(树的点分治)

    1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...

  5. 括号匹配 区间DP (经典)

    描述给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来 ...

  6. HDU4812 D Tree(树的点分治)

    题目大概说给一棵有点权的树,输出字典序最小的点对,使这两点间路径上点权的乘积模1000003的结果为k. 树的点分治搞了.因为是点权过根的两条路径的LCA会被重复统计,而注意到1000003是质数,所 ...

  7. YTU 3003: 括号匹配(栈和队列)

    3003: 括号匹配(栈和队列) 时间限制: 1 Sec  内存限制: 128 MB 提交: 2  解决: 2 [提交][状态][讨论版] 题目描述 假设一个表达式中只允许包含三种括号:圆括号&quo ...

  8. C++,利用链式栈实现括号匹配,界面友好,操作方便,运行流畅

    #include<iostream> #include<string> using namespace std; struct Node { char ch; Node* ne ...

  9. [原]NYOJ 括号匹配系列2,5

    本文出自:http://blog.csdn.net/svitter 括号匹配一:http://acm.nyist.net/JudgeOnline/problem.php?pid=2 括号匹配二:htt ...

随机推荐

  1. java版的下雪,大家圣诞快乐

    1. [代码][Java]代码    package com.yk.tools.game; import java.applet.AudioClip;import java.awt.Dimension ...

  2. 网络流量分析——NPMD关注IT运维、识别宕机和运行不佳进行性能优化。智能化分析是关键-主动发现业务运行异常。科来做APT相关的安全分析

    科来 做流量分析,同时也做了一些安全分析(偏APT)——参考其官网:http://www.colasoft.com.cn/cases-and-application/network-security- ...

  3. python sorted函数的小练习

    前两天学习了一下socket编程,在向某大神请教问题时被嫌弃了,有一种还没学会走就想跑的感觉.大神说我现在的水平应该去做一些像是操作文件.序列号等的小练习来加深理解.下面是他给我出的小练习: 1.da ...

  4. 003-更改pip的源让下载安装更加快捷

    1 找到pip目录 C:\Python36\Lib\site-packages\pip\models 2 修改下面的index.py文件 将url设定为 https://pypi.douban.com ...

  5. LuoguP4861 按钮

    传送门 这题一眼看上去要解\(k^x \equiv 1(mod\ m)\)的最小正整数解. 于是我打了一个扩展BSGS 这题这样做算的答案一直是0的.不过有另一个定理欧拉定理,\(k^{\varphi ...

  6. 错误 128 无法将类型“string”隐式转换为“System.Windows.Forms.DataGridViewTextBoxColumn”

    原因是DataGridView中列的Name属性值和DataPropertyName属性值一样,比如Name="CardID",DataPropertyName="Car ...

  7. html锚点实现的方法

    1 通过id <a href="#div1"> 通过id获取锚点</a> <div style=" height:200px; width: ...

  8. 深度学习之softmax回归

    前言            以下内容是个人学习之后的感悟,转载请注明出处~ softmax回归 首先,我们看一下sigmod激活函数,如下图,它经常用于逻辑回归,将一个real value映射到(0, ...

  9. mongodb和mysql语法对比

    MySQL: SELECT * FROM user Mongo: db.user.find() —————————————— MySQl: SELECT * FROM user WHERE name ...

  10. 3.1 HiveServer2.Beeline JDBC使用

    https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients 一.HiveServer2.Beeline 1.HiveSer ...