翻轉一個括號使得所有括號都能配對,問一共可以翻轉幾個括號。
AC
方法1:
-
如果某個位置上的右括號數量大于他的左括號的數量那么這個位置及之后的位置無論如何翻轉都不能滿足配對。
例如:())((() 第三個位置:右括號2個,左括號1個,位置3之后的括號無論如何變化,第三個位置上的狀態都不會改變。
-
同理如果從右邊開始考慮,如果某個位置上的右括號數量小于左括號數量,之后位置上的括號也是不能匹配
例如:((()(() 第五個位置:右括號1個,左括號兩個。那么位置5之前的括號無論如何變化,位置5的狀態都不會改變。
-
為什么考慮左右的不考慮當下的?因為:雖然當前位置不符合匹配的要求“(()”,但是我可以通過翻轉改變呀。
-
用L,R數組記錄括號前后綴數量和,之后枚舉每個括號,判斷能否翻轉使得匹配
方法2:
- 要想翻轉一個使得整體括號匹配,只能多出來2個左括號或者2個右括號
- 假如多2個左括號,我們最左邊開始判斷,如果當前位置為左括號且左括號的前綴和大于等于2,那么翻轉這個位置就可以使得整個括號匹配。
- 假如多2個右括號,我們最左邊開始判斷,如果當前位置為右括號且左括號的前綴和大于等于-2,那么翻轉這個位置就可以使得整個括號匹配。
- 當我們求完前綴和之后,需要從后向前更新最小值,這樣能保證翻轉前面的區間的同時后面的區間也能滿足。
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define N 1000005
using namespace std
;int L
[N
], R
[N
];
int Fl
[N
], Fr
[N
];
char s
[N
];
int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);
#endifint n
;while (scanf("%d%s", &n
, s
+1) != EOF) {Fl
[0] = 1;Fr
[n
+1] = 1;mem(L
, 0);mem(R
, 0);for (int i
= 1; i
<= n
; ++i
) {if (s
[i
] == '(') L
[i
] = L
[i
-1] + 1;else L
[i
] = L
[i
-1] - 1;Fl
[i
] = (Fl
[i
-1] && L
[i
] >= 0);}for (int i
= n
; i
>= 1; --i
) {if (s
[i
] == ')') R
[i
] = R
[i
+1] + 1;else R
[i
] = R
[i
+1] - 1;Fr
[i
] = (Fr
[i
+1] && R
[i
] >= 0);}int ans
= 0;for (int i
= 1; i
<= n
; ++i
) {if (Fl
[i
-1] == 0) {break;}if (Fr
[i
+1] == 0) {continue;}if (s
[i
] == ')' && L
[i
-1] + 1 == R
[i
+1]) ans
++;else if (s
[i
] == '(' && L
[i
-1] == R
[i
+1] + 1) ans
++;}cout
<< ans
<< endl
;}return 0;
}
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define N 1000005
using namespace std
;int L
[N
];
char s
[N
];
int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);
#endifint n
;while (scanf("%d%s", &n
, s
+1) != EOF) {REP
(i
, n
) L
[i
] = L
[i
-1] + (s
[i
] == '(' ? 1 : -1);if (L
[n
] != -2 && L
[n
] != 2) {puts("0");continue;}for (int i
= n
-1; i
>= 1; --i
) L
[i
] = min(L
[i
], L
[i
+1]);int cnt
= 0;int ans
= 0;REP
(i
, n
) {if (s
[i
] == '(') {if (L
[i
] >= 2 && L
[n
] == 2) ans
++;cnt
++;}else{if (L
[i
] >= -2 && L
[n
] == -2) ans
++;cnt
--;}if (cnt
< 0) break;}printf("%d\n", ans
);}return 0;
}
總結
以上是生活随笔為你收集整理的Codeforces Round #529 (Div. 3) E. Almost Regular Bracket Sequence (括号配对,前缀和)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。