1. 程式人生 > >Gym 240084E - Correct Bracket Sequence Editor - [線段樹]

Gym 240084E - Correct Bracket Sequence Editor - [線段樹]

can pac esp shu sta pop href max .com

題目鏈接:https://codeforces.com/gym/240084/problem/E

題意:

給出一個已經匹配的括號串,給出起始的光標位置(光標總是指向某個括號)。

有如下操作:

  1、往左移動一下光標;

  2、往左移動一下光標;

  3、刪除當前光標指向的括號,以及和它匹配的那個括號,以及這兩個括號之間的所有括號。

要求你給出在做完所有操作後的括號串。

題解:

用線段樹維護,每個括號是否存在,存在記為 $1$,被刪掉了記為 $0$。

然後我們只需要實現:①區間求和、②區間賦值、③根據 $k$ 求最小的 $x$ 滿足在區間 $[1,x]$ 上求和正好等於 $k$。

移動光標可以通過①和③來完成;刪除可以通過②來刪除,刪除完之後的光標移動依然可以靠①③完成。

時間復雜度是 $O(n + m \log n)$,分別是建樹和 $m$ 次操作的時間復雜度。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int n,m,p;
char s[maxn];
char op[maxn];

#define ls (rt<<1)
#define rs (rt<<1|1)
struct Node{
    
int l,r; int val; bool del; void update() { val=0, del=1; } }o[maxn<<2]; void pushdown(int rt) { if(o[rt].del) { o[ls].update(); o[rs].update(); o[rt].del=0; } } inline void pushup(int rt) { o[rt].val=o[ls].val+o[rs].val; }
void build(int rt,int l,int r) { o[rt].l=l, o[rt].r=r; o[rt].del=0; if(l==r) { o[rt].val=1; return; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); pushup(rt); } void del(int rt,int st,int ed) { if(st<=o[rt].l && o[rt].r<=ed) { o[rt].update(); return; } pushdown(rt); int mid=(o[rt].l+o[rt].r)>>1; if(st<=mid) del(ls,st,ed); if(mid<ed) del(rs,st,ed); pushup(rt); } int sum(int rt,int st,int ed) { if(st>ed) return 0; if(st<=o[rt].l && o[rt].r<=ed) return o[rt].val; pushdown(rt); int mid=(o[rt].l+o[rt].r)>>1; int res=0; if(st<=mid) res+=sum(ls,st,ed); if(mid<ed) res+=sum(rs,st,ed); pushup(rt); return res; } int idx(int rt,int k) { if(o[rt].l==o[rt].r) return 1; pushdown(rt); if(o[ls].val>=k) return idx(ls,k); else return (o[ls].r-o[ls].l+1)+idx(rs,k-o[ls].val); } stack<int> S; int bro[maxn]; int main() { cin>>n>>m>>p; scanf("%s",s+1); for(int i=1;i<=n;i++) { if(s[i]==() S.push(i); if(s[i]==)) bro[S.top()]=i, bro[i]=S.top(), S.pop(); } scanf("%s",op+1); build(1,1,n); for(int q=1;q<=m;q++) { if(op[q]==L) { p=idx(1,sum(1,1,p)-1); } if(op[q]==R) { p=idx(1,sum(1,1,p)+1); } if(op[q]==D) { int st=min(p,bro[p]); int ed=max(p,bro[p]); del(1,st,ed); if(sum(1,ed+1,n)>0) p=idx(1,sum(1,1,ed)+1); else p=idx(1,sum(1,1,st-1)); } } for(int i=1;i<=n;i++) { if(sum(1,i,i)>0) printf("%c",s[i]); } }

Gym 240084E - Correct Bracket Sequence Editor - [線段樹]