• Codeforces Round #603 (Div. 2)


    题意:给你一串指令集,当某个指令为$``L"$时,表示鼠标的光标向左移动一个单位$($如果已经位于最左边,则不移动$)$,当指令为$``R"$时,表示将光标像右移动一个单位,其他的字符$($只有小写字母和左括号、右括号$)$都表示将当前光标指向的字符更改为输入的字符,对于每个指令,输出一个数,如果所得到的文本中括号序列合法,则是输出当前文本最大的括号嵌套层数,括号序列不合法则输出$-1$

    思路:用$1$表示左括号,$-1$表示右括号,$0$表示其他字符,用一个线段树维护三个值:区间和$w$,区间最大前缀和$imax$,区间最小前缀和$imin$。对于任意一个合法的括号序列,需要满足以下两个条件:

    • 左括号和右括号的数量相等,即$w=0$
    • 括号序列的任意前缀和都大于等于$0$,即$imin ge 0$

    而对于一个合法的括号序列,括号的最大嵌套层数就是区间最大前缀和$imax$,需要维护一个单点修改和区间查询的线段树,但由于每次查询的区间都是$[1,n]$,线段树根节点表示的区间正好是$[1,n]$,所以只用维护一个单点修改的线段树,输入小写字母和左括号、右括号时,将光标位置上的值改为对应的值,同时更新区间和,区间最大前缀和,区间最小前缀和,具体更新如下:

    • 区间和$=$左区间和$+$右区间和
    • 最小前缀和$=min($左区间最小前缀和$,$左区间区间和$+$右区间最小前缀和$)$
    • 最大前缀和$=max($左区间最大前缀和$,$左区间区间和$+$右区间最大前缀和$)$

    更新后判断$[1,n]$的括号序列是否合法,不合法输出$-1$,合法则直接输出区间$[1,n]$中$imax$的值

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
     
    using namespace std;
     
    const int N = 1000010;
     
    struct node {
        int l, r, w;
        int imin, imax;
    };
     
    node tree[4 * N];
    int n, res[N];
    char s[N];
     
    void build(int k, int lef, int rig)
    {
        tree[k].l = lef, tree[k].r = rig;
        if (tree[k].l == tree[k].r) {
            tree[k].w = tree[k].imin = tree[k].imax = 0;
            return;
        }
        int mid = (lef + rig) / 2;
        build(k * 2, lef, mid);
        build(k * 2 + 1, mid + 1, rig);
        tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
        tree[k].imax = max(tree[k * 2].imax, tree[k * 2 + 1].imax);
        tree[k].imin = max(tree[k * 2].imin, tree[k * 2 + 1].imin);
    }
     
    void change_point(int k, int x, int y)
    {
        if (tree[k].l == tree[k].r) {
            tree[k].w = y;
            return;
        }
        int mid = (tree[k].l + tree[k].r) / 2;
        if (x <= mid) change_point(2 * k, x, y);
        else change_point(2 * k + 1, x, y);
        tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
        tree[k].imax = max(tree[k * 2].imax, tree[k * 2].w + tree[k * 2 + 1].imax);
        tree[k].imin = min(tree[k * 2].imin, tree[k * 2].w + tree[k * 2 + 1].imin);
    }
     
    int main()
    {
        scanf("%d%s", &n, s + 1);
        build(1, 1, n);
        int cur = 1, len = strlen(s + 1);
        for (int i = 1; i <= len; i++) {
            if ('(' == s[i]) change_point(1, cur, 1);
            else if (')' == s[i]) change_point(1, cur, -1);
            else if ('L' == s[i]) {
                if (cur >= 2) cur--;
            }
            else if ('R' == s[i]) cur++;
            else change_point(1, cur, 0);
            if (0 != tree[1].w || 0 != tree[1].imin) res[i] = -1;
            else res[i] = tree[1].imax;
        }
        for (int i = 1; i <= len; i++) {
            printf("%d", res[i]);
            printf(i == len ? "
    " : " ");
        }
        return 0;
    }
  • 相关阅读:
    SharePoint下载大文件失败 异常信息: system.OutOfMemoryException
    SharePoint Server 2010 容量管理:软件边界和限制
    PowerShell 备份sharepoint站点命令
    SharePoint 开发自定义WebService
    SPCAMLEditor 10分钟打造一个在线视频播放库
    使用PowerShell批量注册DLL到GAC
    设计模式之二 策略模式
    (转)Github上的热门iOS开源项目:AFNetworking、MagicalRecord、BlocksKit以及XVim
    (转)iOS开发常用的宏 大家一起来收集~
    (转)iOS开发资源:推送通知相关开源项目PushSharp、APNSPHP以及Pyapns等
  • 原文地址:https://www.cnblogs.com/zzzzzzy/p/12115114.html
Copyright © 2020-2023  润新知