51Nod-1791-合法括号子段
2017-07-31 11:40
357 查看
ACM模版
一开始,并没有仔细区分这个概念,搞得有些手足无措,后来想通了,就是一个简单的分治,分别控制子段的左右两端点在左右两个区间内,然后从中间开始查找,控制左右两个半区间的合法性即可。没什么难度,细心即可。
五级题中也有一个和这个题异曲同工之效的,记不清题号了……
描述
题解
这里,我们需要明确区分一个定义,什么叫做子段?什么叫做子序列?子段是子序列的一种,也叫做连续子序列,而子序列呢?如果不要求连续,则是可以从原序列中任意取,但是要保持原先的先后顺序即可。一开始,并没有仔细区分这个概念,搞得有些手足无措,后来想通了,就是一个简单的分治,分别控制子段的左右两端点在左右两个区间内,然后从中间开始查找,控制左右两个半区间的合法性即可。没什么难度,细心即可。
五级题中也有一个和这个题异曲同工之效的,记不清题号了……
代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 1e6 + 1e5 + 10; const int INF = 0x3f3f3f3f; ll ans; char s[MAXN]; int mn[MAXN]; int mx[MAXN]; int sum_r[MAXN]; int sum_l[MAXN]; int cnt[MAXN << 1]; void solve(int l, int r) { if (l >= r) { return ; } int m = (l + r) >> 1; solve(l, m); solve(m + 1, r); mn[m] = INF; sum_r[m] = 0; for (int i = m + 1; i <= r; i++) { sum_r[i] = sum_r[i - 1] + (s[i] == '(' ? 1 : -1); mn[i] = min(mn[i - 1], sum_r[i]); if (-mn[i] <= -sum_r[i]) // 控制左区段的合法性 { cnt[-sum_r[i] + MAXN]++; } } sum_l[m + 1] = mx[m + 1] = 0; for (int i = m; i >= l; i--) { sum_l[i] = sum_l[i + 1] + (s[i] == '(' ? 1 : -1); mx[i] = max(mx[i + 1], sum_l[i]); if (sum_l[i] >= mx[i + 1]) { ans += cnt[sum_l[i] + MAXN]; } } for (int i = m + 1; i <= r; i++) { if (-mn[i] <= -sum_r[i]) // 重置 { cnt[-sum_r[i] + MAXN]--; } } } int main() { int T; scanf("%d", &T); while (T--) { ans = 0; scanf("%s", s + 1); int len = (int)strlen(s + 1); solve(1, len); printf("%lld\n", ans); } return 0; }
相关文章推荐
- 51nod 1791 合法括号子段 (dp)
- 51Nod 1791 合法括号子段(栈+乱搞)
- 51nod 1791 合法括号子段 DP
- 合法括号子段 51Nod - 1791 **
- 51nod 1791 合法括号子段(DP)
- 51nod 1791 合法括号子段
- 51NOD 1791 合法括号子段
- 51nod 1791 合法括号子段(模拟)
- 51nod 1791 合法括号子段 (队列)
- 51nod 1791 合法括号子段
- 51nod-1791-合法括号子段
- 合法括号子段 51Nod - 1791 (栈+dp)
- 51nod_1791——合法括号字段
- 1791 合法括号子段
- 【51nod 1791】 合法括号子段
- 51nod 合法括号子段
- 51 Nod 1791 合法括号子段【分治+字符串】
- 合法括号子段
- 【51Nod1791】合法括号子段
- [分治] 51nod算法马拉松27 A.合法括号子段