Codeforces 670E - Correct Bracket Sequence Editor - [線段樹]

題目連接:https://codeforces.com/contest/670/problem/Ehtml

 

題意:c++

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

有以下操做:spa

  一、往左移動一下光標;code

  二、往左移動一下光標;htm

  三、刪除當前光標指向的括號,以及和它匹配的那個括號,以及這兩個括號之間的全部括號。blog

要求你給出在作完全部操做後的括號串。ci

 

題解:get

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

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

移動光標能夠經過①和③來完成;刪除能夠經過②來刪除,刪除完以後的光標移動依然能夠靠①③完成。

時間複雜度是 $O(n + m \log n)$,分別是建樹的 $O(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]);
    }
}
相關文章
相關標籤/搜索