您的位置:首页 > 产品设计 > UI/UE

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

2015-08-19 23:28 791 查看
题目大意:

就是对于一个由'('和')‘组成的括号序列, 现在又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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息