UESTC 94 Bracket Sequence (线段树 区间修改)

题目大意:

就是对于一个由'('和')‘组成的括号序列, 现在又3种操作, 第一种是将某个区间的所有括号修改成'('或者')', 第二种是将某个区间的所有字符反向'('变成')', ')'变成'(', 第三种是询问某个区间中的括号序列是否是一个号的序列

定义好的序列:

1.空序列是好序列

2.如果A是好序列那么'(' + A + ')'也是好序列

3. 如果A, B是好序列那么A + B也是好序列


大致思路:

考虑用线段树维护的时候, 两个序列的合并问题

注意到一个序列是好序列, 如果我们用1表示'(', -1表示')'那么

从左边开始前缀和都不能小于0, 且到结尾和为0的序列是好序列

于是考虑维护前缀和最小值和区间和这两个值, 但是当出现reverse操作时会发现只考这两个值是不够的, 还需要前缀和的最大值, 每次反转之后前缀和最小值是原来最大值的相反数, 前缀和最大值时原来最小值的相反数, 总和是原来总和的相反数

那么在更新的时候两个节点向上合并的转移也就很简单了

考虑区间修改操作, 两种操作和异或+覆盖很像, 需要用两个懒惰标记且覆盖标记优先级高于异或标记, 那么这个题到这里思路就很明显了


代码如下:

Result  :  Accepted     Memory  :  6216 KB     Time  :  262 ms

/*
 * Author: Gatevin
 * Created Time:  2015/8/19 22:14:32
 * File Name: Sakura_Chiyo.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

#define maxn 100010

struct Segment_Tree
{
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    struct State
    {
        int min, max, all;
        State(int _mi, int _ma, int _al)
        {
            min = _mi, max = _ma, all = _al;
        }
        State(){}
    };
    State s[maxn << 2];
    int cover[maxn << 2];
    int rev[maxn << 2];
    char in[maxn];
    
    void pushUp(int rt)
    {
        s[rt] = State(min(s[rt << 1].min, s[rt << 1].all + s[rt << 1 | 1].min),
                      max(s[rt << 1].max, s[rt << 1].all + s[rt << 1 | 1].max),
                      s[rt << 1].all + s[rt << 1 | 1].all);
        return;
    }
    
    void pushDown(int l, int r, int rt, int mid)
    {
        if(cover[rt] != -1)
        {
            cover[rt << 1] = cover[rt << 1 | 1] = cover[rt];
            if(cover[rt] == 1)//change to '('
            {
                s[rt << 1] = State(1, mid - l + 1, mid - l + 1);
                s[rt << 1 | 1] = State(1, r - mid, r - mid);
            }
            else
            {
                s[rt << 1] = State(-(mid - l + 1), -1, -(mid - l + 1));
                s[rt << 1 | 1] = State(-(r - mid), -1, -(r - mid));
            }
            rev[rt << 1] = rev[rt << 1 | 1] = 0;
            cover[rt] = -1;
        }
        if(rev[rt])
        {
            if(cover[rt << 1] != -1) cover[rt << 1] ^= rev[rt];
            else rev[rt << 1] ^= rev[rt];
            if(cover[rt << 1 | 1] != -1) cover[rt << 1 | 1] ^= rev[rt];
            else rev[rt << 1 | 1] ^= rev[rt];
            s[rt << 1] = State(-s[rt << 1].max, -s[rt << 1].min, -s[rt << 1].all);
            s[rt << 1 | 1] = State(-s[rt << 1 | 1].max, -s[rt << 1 | 1].min, -s[rt << 1 | 1].all);
            rev[rt] = 0;
        }
        return;
    }
    
    void build(int l, int r, int rt)
    {
        cover[rt] = -1;
        rev[rt] = 0;
        if(l == r)
        {
            if(in[l] == '(')
                s[rt] = State(1, 1, 1);
            if(in[l] == ')')
                s[rt] = State(-1, -1, -1);
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
        pushUp(rt);
    }
    
    void update(int l, int r, int rt, int L, int R, int value)//change to value
    {
        if(l >= L && r <= R)
        {
            rev[rt] = 0;
            cover[rt] = value;
            if(value == 1) s[rt] = State(1, r - l + 1, r - l + 1);
            else s[rt] = State(-(r - l + 1), -1, -(r - l + 1));
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(l, r, rt, mid);
        if(mid >= L) update(lson, L, R, value);
        if(mid + 1 <= R) update(rson, L, R, value);
        pushUp(rt);
        return;
    }
    
    void update(int l, int r, int rt, int L, int R)//reverse
    {
        if(l >= L && r <= R)
        {
            if(cover[rt] != -1) cover[rt] ^= 1;
            else rev[rt] ^= 1;
            s[rt] = State(-s[rt].max, -s[rt].min, -s[rt].all);
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(l, r, rt, mid);
        if(mid >= L) update(lson, L, R);
        if(mid + 1 <= R) update(rson, L, R);
        pushUp(rt);
        return;
    }
    
    State query(int l, int r, int rt, int L, int R)
    {
        if(l >= L && r <= R)
            return s[rt];
        int mid = (l + r) >> 1;
        pushDown(l, r, rt, mid);
        State s1, s2;
        bool fl = 0, fr = 0;
        if(mid >= L) s1 = query(lson, L, R), fl = 1;
        if(mid + 1 <= R) s2 = query(rson, L, R), fr = 1;
        if(!fl) return s2;
        if(!fr) return s1;
        return State(min(s1.min, s1.all + s2.min), max(s1.max, s1.all + s2.max), s1.all + s2.all);
    }
    
    void solve()
    {
        int n, Q;
        scanf("%d", &n);
        scanf("%s", in);
        build(0, n - 1, 1);
        scanf("%d", &Q);
        char op[100], c[4];
        int l, r;
        State ret;
        while(Q--)
        {
            scanf("%s", op);
            switch(op[0])
            {
                case 'q': scanf("%d %d", &l, &r);
                          ret = query(0, n - 1, 1, l, r);
                          printf("%s\n", (ret.min >= 0 && ret.all == 0) ? "YES" : "NO");
                          break;
                case 's': scanf("%d %d %s", &l, &r, c);
                          update(0, n - 1, 1, l, r, c[0] == '(' ? 1 : 0);
                          break;
                case 'r': scanf("%d %d", &l, &r);
                          update(0, n - 1, 1, l, r);
                          break;
            }
        }
        puts("");
        return;
    }
    
};

Segment_Tree ST;

int main()
{
    int T;
    scanf("%d", &T);
    for(int cas = 1; cas <= T; cas++)
    {
        printf("Case %d:\n", cas);
        ST.solve();
    }
    return 0;
}


你可能感兴趣的:(线段树,sequence,uestc,94,Bracket)