zoukankan      html  css  js  c++  java
  • Codeforces 670E

    题目链接:https://codeforces.com/contest/670/problem/E

    题意:

    给出一个已经匹配的括号串,给出起始的光标位置(光标总是指向某个括号)。

    有如下操作:

      1、往左移动一下光标;

      2、往左移动一下光标;

      3、删除当前光标指向的括号,以及和它匹配的那个括号,以及这两个括号之间的所有括号。

    要求你给出在做完所有操作后的括号串。

    题解:

    用线段树维护,每个括号是否存在,存在记为 $1$,被删掉了记为 $0$。

    然后我们只需要实现:①区间求和、②区间赋值、③根据 $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]);
        }
    }
  • 相关阅读:
    css实现截取文本
    ob_clean()解决php验证码图片无法显示
    JS获取url参数,修改url参数
    mysql模糊查询特殊字符(\,%和_)处理
    apache反向代理和监听多个端口设置
    页面底部自适应浏览器窗口高度
    变量相关考虑
    php非法输入数据类型
    php socket模拟http中post或get提交数据
    华为专利的 hybrid 端口
  • 原文地址:https://www.cnblogs.com/dilthey/p/10503952.html
Copyright © 2011-2022 走看看