终于还是写完了。。懒癌复发。。。原来可以用线段树。判断区间内最小的前缀是否小于2就行了。。。之前比赛的时候没有想到用这个方法。。。虽然自己会一点线段树。。但是可惜没写出来。。总的来说还是太菜了吧。要多刷刷线段树。。刷完线段树接下来就是最短路、最小生成树、DP了。
G - Parenthesis
Time Limit:5000MS Memory Limit:131072KB 64bit IO Format:%lld & %llu
Appoint description:
Description
Bobo has a balanced parenthesis sequence P=p
1 p
2…p
n of length n and q questions.
The i-th question is whether P remains balanced after p
ai and p
bi swapped. Note that questions are individual so that they have no affect on others.
Parenthesis sequence S is balanced if and only if:
1.
S is empty;
2.
or there exists
balanced parenthesis sequence A,B such that S=AB;
3.
or there exists
balanced parenthesis sequence S' such that S=(S').
Input
The input contains at most 30 sets. For each set:
The first line contains two integers n,q (2≤n≤10
5,1≤q≤10
5).
The second line contains n characters p
1 p
2…p
n.
The i-th of the last q lines contains 2 integers a
i,b
i (1≤a
i,b
i≤n,a
i≠b
i).
Output
For each question, output "
Yes" if P remains balanced, or "
No" otherwise.
Sample Input
4 2
(())
1 3
2 3
2 1
()
1 2
Sample Output
No
Yes
No
#include<bits/stdc++.h> using namespace std; const int MAXN=1e5+5; const int INF=0x3f3f3f3f; int sum[MAXN<<2]; int pre[MAXN]; char s[MAXN]; void push_up(int k) { sum[k]=min(sum[k<<1],sum[k<<1|1]); } void build(int l,int r,int k) { if(l==r) { sum[k]=pre[l]; return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); push_up(k); } int query(int L,int R,int l,int r,int k) { if(L<=l&&R>=r) return sum[k]; int ans=INF; int mid=(l+r)>>1; if(L<=mid) ans=min(ans,query(L,R,l,mid,k<<1)); if(R>mid) ans=min(ans,query(L,R,mid+1,r,k<<1|1)); return ans; } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { scanf("%s",s+1); for(int i=1;i<=n;i++) { if(s[i]=='(') pre[i]=pre[i-1]+1; else pre[i]=pre[i-1]-1; } build(1,n,1); while(m--) { int l,r; scanf("%d%d",&l,&r); if(l>r)swap(l,r); if(s[l]==s[r]||(s[l]==')'&&s[r]=='(')) printf("Yes\n"); else { if(query(l,r-1,1,n,1)<2) printf("No\n"); else printf("Yes\n"); } } } return 0; }