1809: Parenthesis
Time Limit: 5 Sec Memory Limit: 128 Mb Submitted: 1149 Solved: 326
Description
Input
Output
Sample Input
4 2 (()) 1 3 2 3 2 1 () 1 2
Sample Output
No Yes No
题目链接:CSU 1809
下午又被同学叫去做做题,大约是湖南省某套题目,这回太excited的啦,直接爆零滚粗,然后各种查题解,虽然发现题目难度确实不小且解题程序代码量基本都比较大(其中感觉最骚的是那道地铁,没见过这么骚的建模),但是还是想做几题,然后晚上没事儿看看其他OJ突然发现某篇另外的其他地方的比赛题解里有讲到一种简单的判断括号序列的方法:记左括号为1,右括号为-1,求出前缀和,若结尾为0且前缀和序列没有负数,则说明括号序列合法,然后又想到这题应该可以好好利用这个方法做
那么跟这一题有什么关系呢?考虑题目中所说交换的情况,共四种,除去很容易想到的等价的交换两种(左括号交换左括号,右括号交换右括号),还有左-右与右-左两种,然后我们放到前缀和序列上来考虑,首先你得特判,若开头或结尾处被交换必定不合法(此处已除去等价交换的情况),因为开头必定是'('而结尾必定是')';然后再考虑中间的交换,我们方便一点令a<b(交换本来就是可逆的,a、b互换不影响结果),若'('与')'交换,则说明1被换到后面,-1被换到前面,这里我们分为三步,先把1拿出来,再把-1放到a位置,再把1放到b位置,我们会发现前缀$prefix_{a...b-1}$改变了-2,而$prefix_{b...n}$显然是不变的,那么只需判断改变前的一段是否均大于等于2以至于均-2后不会出现0;再考虑另外一种')'与'('交换,若按前面的前缀和打个草稿会发现这样做一定是合法的,改变一段的值一定为正,那么这题就用RMQ-ST就可以了,代码量不大,但是由于第二种情况忘记分开讨论了Debug很久……
代码:
#include <stdio.h> #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LC(x) (x<<1) #define RC(x) ((x<<1)+1) #define MID(x,y) ((x+y)>>1) #define CLR(arr,val) memset(arr,val,sizeof(arr)) #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); typedef pair<int, int> pii; typedef long long LL; const double PI = acos(-1.0); const int N = 1e5 + 7; char s[N]; int prefix[N], Min[N][18]; void init() { prefix[0] = 0; CLR(Min, INF); } void RMQ_init(int l, int r) { int i, j; for (i = l; i <= r; ++i) Min[i][0] = min<int>(Min[i][0], prefix[i]); for (j = 1; l + (1 << j) - 1 <= r; ++j) { for (i = l; i + (1 << j) - 1 <= r; ++i) { Min[i][j] = min<LL>(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]); } } } int ST(int l, int r) { int k = log2(r - l + 1.0); return min(Min[l][k], Min[r - (1 << k) + 1][k]); } int main(void) { int n, q, i; while (~scanf("%d%d", &n, &q)) { init(); scanf("%s", s + 1); for (i = 1; i <= n; ++i) prefix[i] = prefix[i - 1] + (s[i] == '(' ? 1 : -1); RMQ_init(1, n); while (q--) { int a, b; scanf("%d%d", &a, &b); if (a > b) swap(a, b); if (s[a] == s[b]) puts("Yes"); else { if (a == 1 || b == n || (ST(a, b - 1) < 2 && s[a] == '(' && s[b] == ')')) puts("No"); else puts("Yes"); } } } return 0; }