[CSU 1809: Parenthesis] 线段树处理括号序列
题目链接:[CSU 1809: Parenthesis]
题意描述:给定一个长度为N的”平衡”的括号序列。Q次询问。每次询问,包含
a,b
表示将第
a
个字符与第
解题思路:首先,处理出前缀和。
- 序列中第
i
个字符是 ‘(‘,
pre[i]=pre[i]+1 ; - 序列中第
i
个字符是 ‘)’,
pre[i]=pre[i]−1 ;
这样, 又因为最初的序列是平衡的。当序列不“平衡”当且仅当存在一个数k,使得
pre[k]<0(1≤k≤N)
。
只需要用线段树或者RMQ维护区间最小值。
当将第
a
个字符与第
我们单独考虑
buf[a]=′(′并且buf[b]=′)′
的情况,这个时候,交换第
a
个字符与第
/**
* 线段树
*/
#include <ctime>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define lson l, mid, (rt << 1)
#define rson mid + 1, r, (rt << 1 | 1)
#define _mid_ int mid = (l + r) >> 1
typedef long long LL;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int N, Q;
char buf[MAXN];
int pre[MAXN], seg[MAXN << 2];
inline void pushUp(int rt) {
seg[rt] = min(seg[rt << 1], seg[rt << 1 | 1]);
}
void build(int l, int r, int rt) {
if(l == r) {
seg[rt] = pre[l];
return;
}
_mid_;
build(lson);
build(rson);
pushUp(rt);
}
int query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return seg[rt];
}
_mid_;
int ret = INF;
if(L <= mid) ret = query(L, R, lson);
if(R > mid) ret = min(ret, query(L, R, rson));
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
int a, b;
while(~scanf("%d %d", &N, &Q)) {
scanf("%s", buf + 1);
pre[0] = 0;
for (int i = 1; i <= N; i++) {
if(buf[i] == '(') pre[i] = pre[i - 1] + 1;
else pre[i] = pre[i - 1] - 1;
}
build(1, N, 1);
while(Q --) {
scanf("%d %d", &a, &b);
if(a > b) swap(a, b);
if(buf[a] == buf[b] || (buf[a] == ')' && buf[b] == '(')) {
printf("Yes\n");
} else {
int mi = query(a, b - 1, 1, N, 1);
if(mi < 2) printf("No\n");
else printf("Yes\n");
}
}
}
return 0;
}
/**
* RMQ
*/
#include <ctime>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define FIN freopen("input.txt","r",stdin)
#define lson l, mid, (rt << 1)
#define rson mid + 1, r, (rt << 1 | 1)
#define _mid_ int mid = (l + r) >> 1
typedef long long LL;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int N, Q;
char buf[MAXN];
int pre[MAXN];
int dp[MAXN][20];
int mm[MAXN];
void initRMQ(int n, int b[]) {
mm[0] = -1;
for(int i = 1; i <= n; i++) {
mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
dp[i][0] = b[i];
}
for(int j = 1; j <= mm[n]; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}
int rmq(int x, int y) {
int k = mm[y - x + 1];
return min(dp[x][k], dp[y - (1 << k) + 1][k]);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
int a, b;
while(~scanf("%d %d", &N, &Q)) {
scanf("%s", buf + 1);
pre[0] = 0;
for (int i = 1; i <= N; i++) {
if(buf[i] == '(') pre[i] = pre[i - 1] + 1;
else pre[i] = pre[i - 1] - 1;
}
initRMQ(N, pre);
while(Q --) {
scanf("%d %d", &a, &b);
if(a > b) swap(a, b);
if(buf[a] == buf[b] || (buf[a] == ')' && buf[b] == '(')) {
printf("Yes\n");
} else {
int mi = rmq(a, b - 1);
if(mi < 2) printf("No\n");
else printf("Yes\n");
}
}
}
return 0;
}