티스토리 뷰

BOJ

[BOJ] 20052 괄호 문자열 ?

[gunwookim] 2021. 8. 4. 01:06

https://www.acmicpc.net/problem/20052

 

20052번: 괄호 문자열 ?

괄호 문자열은 '('와 ')'로 이루어진 문자열이고, 올바른 괄호 문자열은 다음과 같이 정의된다. 빈 문자열은 올바른 괄호 문자열이다. S가 올바른 괄호 문자열일 때, (S)도 올바른 괄호 문자열이

www.acmicpc.net


'('을 1, ')'을 -1이라 가정한다.

만약 어떤 구간 [l,r]이 올바른 괄호 문자열이 아니라면 ')'가 '('보다 많아지는 순간이 있을 것이다.

이를 누적합으로 표현해보면 l부터 누적으로 더하다가 0보다 작아지는 경우와 ')'가 '('보다 많아지는 경우은 동치이다.

따라서 구간의 누적합을 구하고, 누적합들의 최솟값이 0보다 작아지는 경우가 있는지 검사해보는 식으로 바꿀 수 있다.

하지만 모든 구간마다 최대 \(O(N)\) 번 해보게 되어 총 \(O(NQ)\) 가 걸려 TLE가 나게 된다.

 

일단 누적합을 sum배열에 저장해 둔다.

그리고 [l,r] 구간안에서의 sum배열의 최솟값을 구하고, sum[l-1]을 빼주면, [l,r] 구간에서의 누적합 최솟값이 나오게 된다.

이를 통해 누적합 배열을 구하고, 최소 세그먼트 트리를 구성해두면, 각 쿼리당 \(O(logN)\) 의 시간복잡도에 처리할 수 있게 되어 총 \(O((N+Q)logN)\)의 시간복잡도로 문제를 해결 할 수 있다.

 

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define all(v) v.begin(),v.end()
#pragma gcc optimize("O3")
#pragma gcc optimize("Ofast") 
#pragma gcc optimize("unroll-loops")
using namespace std;
const int INF = 1e9;
const int TMX = 1 << 18;
const long long llINF = 1e18+10;
const long long mod = 1e9+7;
const long long hashmod = 100003;
const int MAXN = 100000;
const int MAXM = 1000000;
typedef long long ll;
typedef long double ld;
typedef pair <int,int> pi;
typedef pair <ll,ll> pl;
typedef vector <int> vec;
typedef vector <pi> vecpi;
typedef long long ll;
int n,sum[100005],t[400005];
char a[100005];

void build(int x,int l,int r) {
	if(l == r) {t[x] = sum[l]; return;}
	int mid = (l + r) >> 1;
	build(x*2,l,mid), build(x*2+1,mid+1,r);
	t[x] = min(t[x*2],t[x*2+1]);
}

int query(int x,int l,int r,int rl,int rr) {
	if(rl > r||l > rr) return INF;
	if(rl <= l&&r <= rr) return t[x];
	int mid = (l + r) >> 1;
	return min(query(x*2,l,mid,rl,rr),query(x*2+1,mid+1,r,rl,rr));
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(0);
	cin >> a+1;
	n = strlen(a+1);
	for(int i = 1;i <= n;i++) sum[i] = sum[i-1]+(a[i] == '(' ? 1 : -1);
	build(1,1,n);
	int Q,ans = 0; cin >> Q;
	while(Q--) {
		int l,r; cin >> l >> r;
		ans += (query(1,1,n,l,r) >= sum[l-1]&&sum[r] == sum[l-1]);
	}
	cout << ans;
}

'BOJ' 카테고리의 다른 글

[BOJ] 6461 Hotel  (0) 2021.08.07
[BOJ] 18919 Allowed Swaps  (0) 2021.08.05
[BOJ] 15311 약 팔기  (0) 2021.08.03
[BOJ] 17958 Cycle String?  (0) 2021.08.03
[BOJ] 4011 기름 파기  (0) 2021.08.03
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함