CSU-2099: Flipping Parentheses

2099: Flipping Parentheses

Submit Page      Summary      Time Limit: 5 Sec       Memory Limit: 512 Mb       Submitted: 49       Solved: 7    

Description

A string consisting only of parentheses ‘(’ and ‘)’ is called balanced if it is one of the following.

  • A string “()” is balanced.
  • Concatenation of two balanced strings are balanced.
  • When a string s is balanced, so is the concatenation of three strings “(”, s, and “)” in this order.

Note that the condition is stronger than merely the numbers of ‘(’ and ‘)’ are equal. For instance, “())(()” is not balanced.

Your task is to keep a string in a balanced state, under a severe condition in which a cosmic ray may flip the direction of parentheses.

You are initially given a balanced string. Each time the direction of a single parenthesis is flipped, your program is notified the position of the changed character in the string. Then, calculate and output the leftmost position that, if the parenthesis there is flipped, the whole string gets back to the balanced state. After the string is balanced by changing the parenthesis indicated by your program, next cosmic ray flips another parenthesis, and the steps are repeated several times.

Input

The input consists of a single test case formatted as follows. 

N Qsq1qQN Qsq1⋮qQ

The first line consists of two integers  N and  Q ( 2 ≤ N ≤ 3000001 ≤ Q ≤ 150000). The second line is a string  s of balanced parentheses with length  N. Each of the following  Q lines is an integer  qi ( 1 ≤ qi ≤ N) that indicates that the direction of the  qi-th parenthesis is flipped.

Output

For each event qi, output the position of the leftmost parenthesis you need to flip in order to get back to the balanced state.

Note that each input flipping event qi is applied to the string after the previous flip qi − 1 and its fix.

Sample Input

6 3
((()))
4
3
1

20 9
()((((()))))()()()()
15
20
13
5
3
10
3
17
18

Sample Output

2
2
1
2
20
8
5
3
2
2
3
18

Hint

In the first sample, the initial state is “((()))”. The 4th parenthesis is flipped and the string becomes “(((())”. Then, to keep the balance you should flip the 2nd parenthesis and get “()(())”. The next flip of the 3rd parenthesis is applied to the last state and yields “())())”. To rebalance it, you have to change the 2nd parenthesis again yielding “(()())”.

Source

Asia Regional Contest, Tokyo, 2014

题意:如果左右括号一一配对成功,则说明当前字符串是平衡的!一开始给定一个平衡的括号字符串,长度为n。有m次操作,每次操作输入t,将第t个括号反转,问改变哪一个括号可以使字符串重新平衡(尽量左边)反转该位置的括号并输出位置k!

题解:我们定义左括号为1, 右括号为-1,接下来分两种情况。

情况1:操作将左括号(反转;只需要将最左边的右括号反转即可!即查找最左边的最小值(-1);

情况2:操作将右括号)反转;此时将前缀和大于等于2的左括号反转都可以;证明链接:http://www.cnblogs.com/qscqesze/p/5143789.html  ;真的大佬。。。

为了实现以上操作,暴力遍历复杂度O(n * m),不可取。使用二分线段树加速,复杂度为O(m * log(n) * log(n));

二分线段树第一次见;

对于最小值,每次查找(1,m)中的最小值,若有等于-1的则r = m,否则l = m + 1; 

对于前缀和,每次查找(m, t)中的最小值,若有小于2的则l = m + 1, 否则r = m;

以上每次操作为(log(n) * log(n))

当然最小值的查找可以优化成log(n),加入一个第二优先级id,代表位置,当值相同时优先取id小的。

AC代码

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
 
using namespace std;

const int maxn = 300010;

struct node{
	int pre, lazy, Min;
}tree[maxn << 2];

void bulid(int l, int r, int rt){
	tree[rt].pre = tree[rt].lazy = 0;
	tree[rt].Min = maxn;
	if(l == r){
		return ;
	}
	int m = (l + r) >> 1;
	bulid(lson);
	bulid(rson);
}

void push_up(int rt){
	tree[rt].pre = min(tree[rt << 1].pre, tree[rt << 1 | 1].pre);
}

void push_down(int rt){
	tree[rt << 1].lazy += tree[rt].lazy;
	tree[rt << 1].pre += tree[rt].lazy;
	tree[rt << 1 | 1].pre += tree[rt].lazy;
	tree[rt << 1 | 1].lazy += tree[rt].lazy;
	tree[rt].lazy = 0;
}

void update_Min(int p, int x, int l, int r, int rt){
	if(l == r){
		tree[rt].Min = x;
		return ;
	}
	int m = (l + r) >> 1;
	if(p <= m)
		update_Min(p, x, lson);
	else
		update_Min(p, x, rson);
	tree[rt].Min = min(tree[rt << 1].Min, tree[rt << 1 | 1].Min);
}

void update_pre(int L, int R, int x, int l, int r, int rt){
	if(L <= l && r <= R){
		tree[rt].pre += x;
		tree[rt].lazy += x;
		return;
	}
	push_down(rt);
	int m = (l + r) >> 1;
	if(m >= L)
		update_pre(L, R, x, lson);
	if(m < R)
		update_pre(L, R, x, rson);
	push_up(rt);
}

int query_Min(int L, int R, int l, int r, int rt){
	if(L <= l && r <= R)
		return tree[rt].Min;
	int ret = maxn;
	int m = (l + r) >> 1;
	if(m >= L)
		ret = min(ret, query_Min(L, R, lson));
	if(m < R)
		ret = min(ret, query_Min(L, R, rson));
	return ret;
}

int query_pre(int L, int R, int l, int r, int rt){
	if(L <= l && r <= R)
		return tree[rt].pre;
	push_down(rt);
	int ret = maxn;
	int m = (l + r) >> 1;
	if(m >= L)
		ret = min(ret, query_pre(L, R, lson));
	if(m < R)
		ret = min(ret, query_pre(L, R, rson));
	push_up(rt);
	return ret;
}

char a[maxn];

int main(){
	int n, m, t;
	while(scanf("%d %d", &n, &m) != EOF){
		scanf("%s", a + 1);
		bulid(1, n , 1);
		for(int i = 1; i <= n; i++){
			if(a[i] == '('){
				update_Min(i, 1, 1, n, 1);
				update_pre(i, n, 1, 1, n, 1);
			}
			else{
				update_Min(i, -1, 1, n, 1);
				update_pre(i, n, -1, 1, n, 1);
			}
		}
		for(int i = 1; i <= m; i++){
			scanf("%d", &t);
			if(a[t] == '('){
				a[t] = ')';
				update_Min(t, -1, 1, n, 1);
				update_pre(t, n, -2, 1, n ,1);
				int l = 1, r = t;
				while(l < r){
					int mm = (l + r) >> 1;
					if(query_Min(1, mm, 1, n, 1) == -1)
						r = mm;
					else
						l = mm + 1;
				}
				update_Min(l, 1, 1, n, 1);
				update_pre(l, n, 2, 1, n, 1);
				a[l] = '(';
				printf("%d\n", l);
			}
			else{
				a[t] = '(';
				update_Min(t, 1, 1, n, 1);
				update_pre(t, n, 2, 1, n, 1);
				int l = 1, r = t;
				while(l < r){
					int mm = (l + r) >> 1;
					if(query_pre(mm, t, 1, n, 1) < 2)
						l = mm + 1;
					else
						r = mm;
				}
				a[l] = ')';
				update_Min(l, -1, 1, n, 1);
				update_pre(l, n, -2, 1, n, 1);
				printf("%d\n", l);
			}
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_37064135/article/details/80228034