Recently Polycarp started to develop a text editor that works only with correct bracket sequences (abbreviated as CBS).
Note that a bracket sequence is correct if it is possible to get a correct mathematical expression by adding "+"-s and "1"-s to it. For example, sequences "(())()", "()" and "(()(()))" are correct, while ")(", "(()" and "(()))(" are not. Each bracket in CBS has a pair. For example, in "(()(()))":
Polycarp's editor currently supports only three operations during the use of CBS. The cursor in the editor takes the whole position of one of the brackets (not the position between the brackets!). There are three operations being supported:
After the operation "D" the cursor moves to the nearest bracket to the right (of course, among the non-deleted). If there is no such bracket (that is, the suffix of the CBS was deleted), then the cursor moves to the nearest bracket to the left (of course, among the non-deleted).
There are pictures illustrated several usages of operation "D" below.
All incorrect operations (shift cursor over the end of CBS, delete the whole CBS, etc.) are not supported by Polycarp's editor.
Polycarp is very proud of his development, can you implement the functionality of his editor?
The first line contains three positive integers n, m and p (2 ≤ n ≤ 500 000, 1 ≤ m ≤ 500 000, 1 ≤ p ≤ n) — the number of brackets in the correct bracket sequence, the number of operations and the initial position of cursor. Positions in the sequence are numbered from left to right, starting from one. It is guaranteed that n is even.
It is followed by the string of n characters "(" and ")" forming the correct bracket sequence.
Then follow a string of m characters "L", "R" and "D" — a sequence of the operations. Operations are carried out one by one from the first to the last. It is guaranteed that the given operations never move the cursor outside the bracket sequence, as well as the fact that after all operations a bracket sequence will be non-empty.
Print the correct bracket sequence, obtained as a result of applying all operations to the initial sequence.
8 4 5
(())()()
RDLD
()
12 5 3
((()())(()))
RRDLD
(()(()))
8 8 8
(())()()
LLLLLLDD
()()
题意:刚开始给你n,m,p (2 < =n <= 500 000, 1 <= m <= 500 000, 1 <=p <= n),然后给你一个长度为n的匹配括号串,对于每一个括号都有与它相匹配的左括号和右括号,
刚开始人所在的位置是p,有3种操作
L表示人向左走一格,R表示人向右走一格,D表示删除这个括号和与其相匹配的括号之间所有的括号
输出最后的括号序列
括号匹配可以用栈来实现
方法一:
线段树,第一种操作相当于向左找到一个没有被删除的括号,第二种操作相当于向右找到一个没有被删除的括号,第三种操作是将匹配的括号之间全部删除,也就是相当于
把这个区间置0(原来全部初始化为1)
方法二:
set,我们可以发现每个位置最多被删除一次,所以我们刚开始将全部位置全部插入到set中,又因为每个位置只会被删除一次,所以我们每次删除的时候可以暴力删除
方法三:
链表,时间复杂度O(n+m)
方法一代码:
#include<bits/stdc++.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 typedef long long ll; const int maxn=501000; int ln[maxn],rn[maxn],st[maxn],setv[maxn*4],maxv[maxn*4],L,R,P; char s[maxn],str[maxn]; void build(int l,int r,int rt){ maxv[rt]=1,setv[rt]=-1; if(l==r) return ; int mid=(l+r)>>1; build(lson); build(rson); } void pushdown(int rt){ if(setv[rt]==0){ setv[rt<<1]=setv[rt<<1|1]=0; maxv[rt<<1]=maxv[rt<<1|1]=0; setv[rt]=-1; } } int query1(int l,int r,int rt){ if(l==r) return l; pushdown(rt); int mid=(l+r)>>1; int ret=0; if(R>mid&&maxv[rt<<1|1]!=0) ret=query1(rson); if(L<=mid&&maxv[rt<<1]!=0&&ret==0) ret=query1(lson); return ret; } int query2(int l,int r,int rt){ if(l==r) return l; pushdown(rt); int mid=(l+r)>>1; int ret=0; if(L<=mid&&maxv[rt<<1]!=0) ret=query2(lson); if(R>mid&&maxv[rt<<1|1]!=0&&ret==0) ret=query2(rson); return ret; } void pushup(int rt){ maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]); } void update(int l,int r,int rt){ if(L<=l&&R>=r){ maxv[rt]=0; setv[rt]=0; return ; } int mid=(l+r)>>1; if(L<=mid) update(lson); if(R>mid) update(rson); pushup(rt); } int query(int l,int r,int rt){ if(l==r) return maxv[rt]; pushdown(rt); int mid=(l+r)>>1; if(P<=mid) return query(lson); else return query(rson); } int main(){ int n,m,p; int tot=0; scanf("%d%d%d",&n,&m,&p); scanf("%s",s+1); for(int i=1;i<=n;i++){ ln[i]=rn[i]=i; if(s[i]=='(') st[tot++]=i; else{ tot--; rn[st[tot]]=i; ln[i]=st[tot]; } } build(1,n,1); int pos=p; scanf("%s",str+1); for(int i=1;i<=m;i++){ if(str[i]=='L'){ L=1,R=pos-1; pos=query1(1,n,1); } else if(str[i]=='R'){ L=pos+1,R=n; pos=query2(1,n,1); } else{ if(s[pos]=='('){ L=pos,R=rn[pos]; update(1,n,1); } else{ L=ln[pos],R=pos; update(1,n,1); } int pos1=pos; L=pos+1,R=n; pos=query2(1,n,1); if(pos==0){ L=1,R=pos1-1; pos=query1(1,n,1); } } } for(int i=1;i<=n;i++){ P=i; if(query(1,n,1)==1) printf("%c",s[i]); } printf("\n"); } /* 6 2 5 (())() DD */
方法三代码:
#include<bits/stdc++.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 typedef long long ll; const int maxn=501000; int ln[maxn],rn[maxn],st[maxn],p; int l[maxn],r[maxn]; char s[maxn],str[maxn]; int main(){ int n,m,p; int tot=0; scanf("%d%d%d",&n,&m,&p); scanf("%s",s+1); for(int i=1;i<=n;i++){ if(s[i]=='(') st[tot++]=i; else{ tot--; rn[st[tot]]=i; ln[i]=st[tot]; } } r[0]=1; for(int i=1;i<=n;i++) r[i]=i+1,l[i]=i-1; scanf("%s",str+1); for(int i=1;i<=m;i++){ if(str[i]=='L') p=l[p]; else if(str[i]=='R') p=r[p]; else{ if(s[p]=='('){ r[l[p]]=r[rn[p]]; l[r[rn[p]]]=l[p]; if(r[rn[p]]!=n+1) p=r[rn[p]]; else p=l[p]; } else{ l[r[p]]=l[ln[p]]; r[l[ln[p]]]=r[p]; if(r[p]!=n+1) p=r[p]; else p=l[ln[p]]; } } } int x=r[0]; while(x<=n){ printf("%c",s[x]); x=r[x]; } printf("\n"); }