思路:网上说dfs建树然后树形dp,我不是很懂。。。
我的写法是,扫一遍字符串找到每个括号的匹配括号,然后给每个括号一个标,每个匹配括号的
宽度为两者在字符串中的下标差值,高度为它们两个之间的括号的标号最大值-自身的标号 + 1,然后算就好啦。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 4e5 + 7; const int M = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, a[N], id, mx[N << 2], l[N], mp[N]; char s[N]; void update(int pos, int v, int l, int r, int rt) { if(l == r) { mx[rt] = v; return; } int mid = l + r >> 1; if(pos <= mid) update(pos, v, l, mid, rt << 1); if(pos > mid) update(pos, v, mid + 1, r, rt << 1 | 1); mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]); } int getMx(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return mx[rt]; int mid = l + r >> 1; int ans = 0; if(L <= mid) ans = max(ans, getMx(L, R, l, mid, rt << 1)); if(R > mid) ans = max(ans, getMx(L, R, mid + 1, r, rt << 1 | 1)); return ans; } int main(){ int T; scanf("%d", &T); while(T--) { scanf("%s", s + 1); n = strlen(s + 1); for(int i = 1; i <= n; i++) { if(s[i] == '(') a[i] = ++id, mp[id] = i; else a[i] = id, l[i] = mp[id--]; update(i, a[i], 1, n, 1); } LL ans = 0; for(int i = 1; i <= n; i++) { if(s[i] == ')') { int op = (a[i] & 1) ? 1 : -1; int wide = i - l[i]; int hight = getMx(l[i], i, 1, n, 1) - a[i] + 1; ans += 1ll * op * wide * hight; } } printf("%lld\n", ans); } return 0; } /* */