UESTC 1546 Bracket Sequence

2023-05-24,,

                                    Bracket Sequence

Time Limit: 3000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu

[Submit]   [Go Back]   [Status]

Description

There is a sequence of brackets, which supports two kinds of operations.
1. we can choose a interval [l,r], and set all the elements range in this interval to left bracket or right bracket. 
2. we can reverse a interval, which means that for all the elements range in [l,r], if it's left bracket at that time, we change it into right bracket, vice versa.
Fish is fond of "Regular Bracket Sequence", so he want to know whether a interval [l,r] of the sequence is regular or not after doing some opearations.

Let us define a regular brackets sequence in the following way:

1. Empty sequence is a regular sequence. 
2. If S is a regular sequence, then (S) is also a regular sequences. 
3. If A and B are regular sequences, then AB is a regular sequence.

Input

In the first line there is an integer T (T≤10), indicates the number of test cases. Each case begins with a line containing an integers N (N ≤ 100,000 and N is a even number), the size of the initial brackets sequence. The next line contains a string whose length is N consisting of '(' and ')'. In the third of each test case, there is an integer M(M ≤ 100,000) indicates the number of queries. Each of the following M lines contains one operation as mentioned below. The index of the bracket sequence is labeled from 0 to N - 1.

Three operation description:
set l r c: change all the elements range in [l,r] into '(' or ')'.(c is '(' or ')')
reverse l r: reverse the interval [l,r]
query l,r: you should answer that interval [l,r] is regular or not

Output

For each test case, print a line containing the test case number (beginning with 1) on its own line, then the answer for each "query" operation, if the interval is regular, print "YES", otherwise print "NO", one on each line.
Print a blank line after each test case.

Sample Input

1
6
((()))
8
query 0 5
set 0 5 (
query 0 5
reverse 3 5
query 0 5
query 1 4
query 2 3
query 0 4

Sample Output

Case 1:
YES
NO
YES
YES
YES
NO

Hint

Huge input, use "scanf" instead of "cin".

Source

Classic Problem
 
线段树,把左右括号标记成-1,1。。。合法的区间的总和为零,且从左向右的累加和 小于等于 0
维护每个结点的sum max,为方便reserv再多维护一个min reserv时交换max,min的绝对值再成-1
set与reserv并存时,要先reserv再set
 

 #include <iostream>
#include <cstring>
#include <cstdio> #define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 using namespace std; const int maxn=; int setv[maxn<<],rev[maxn<<],sum[maxn<<],mx[maxn<<],mi[maxn<<];
char str[maxn]; void reserve(int rt)
{
sum[rt]=-sum[rt];
swap(mx[rt],mi[rt]);
mx[rt]=-mx[rt];
mi[rt]=-mi[rt];
rev[rt]^=;
} void set(int op,int rt,int len)
{
sum[rt]=op*len;
mx[rt]=sum[rt]>?sum[rt]:;
mi[rt]=sum[rt]<?sum[rt]:;
setv[rt]=op;rev[rt]=;
} void push_down(int rt,int ll,int lr)
{
if(rev[rt])
{
if(setv[rt]) setv[rt]*=-;
else reserve(rt<<),reserve(rt<<|);
rev[rt]=;
}
if(setv[rt])
{
set(setv[rt],rt<<,ll),set(setv[rt],rt<<|,lr);
setv[rt]=;
}
} void push_up(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];
mx[rt]=max(mx[rt<<],sum[rt<<]+mx[rt<<|]);
mi[rt]=min(mi[rt<<],sum[rt<<]+mi[rt<<|]);
} void build(int l,int r,int rt)
{
setv[rt]=rev[rt]=;
if(l==r)
{
sum[rt]=(str[l]=='(')?-:;
mx[rt]=(sum[rt]<)?:;
mi[rt]=(sum[rt]<)?-:;
return;
}
int m=(l+r)>>;
build(lson),build(rson);
push_up(rt);
} void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
if(c) set(c,rt,r-l+);
else reserve(rt);
return ;
}
int m=(l+r)>>;
push_down(rt,m-l+,r-m);
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
push_up(rt);
} int query_sum(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return sum[rt];
}
int m=(l+r)>>,ans=;
push_down(rt,m-l+,r-m);
if(L<=m) ans+=query_sum(L,R,lson);
if(R>m) ans+=query_sum(L,R,rson);
push_up(rt);
return ans;
} int query_max(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return mx[rt];
}
int m=(l+r)>>,ret;
push_down(rt,m-l+,r-m);
if(R<=m) ret=query_max(L,R,lson);
else if(L>m) ret=query_max(L,R,rson);
else ret=max(query_max(L,R,lson),query_sum(L,R,lson)+query_max(L,R,rson));
push_up(rt);
return ret;
} int main()
{
int t,cas=;
char cmd[];
scanf("%d",&t);
while(t--)
{
int n,m;
printf("Case %d:\n",cas++);
scanf("%d",&n);
scanf("%s",str);
build(,n-,);
scanf("%d",&m);
while(m--)
{
scanf("%s",cmd);
if(cmd[]=='s')
{
int a,b; char c[];
scanf("%d%d%s",&a,&b,c);
if(c[]=='(')
update(a,b,-,,n-,);
else if(c[]==')')
update(a,b,,,n-,);
}
else if(cmd[]=='r')
{
int a,b;
scanf("%d%d",&a,&b);
update(a,b,,,n-,);
}
else if(cmd[]=='q')
{
int a,b;
scanf("%d%d",&a,&b);
if(!query_sum(a,b,,n-,)&&!query_max(a,b,,n-,)) puts("YES");
else puts("NO");
}
}
putchar();
}
return ;
}

UESTC 1546 Bracket Sequence的相关教程结束。

《UESTC 1546 Bracket Sequence.doc》

下载本文的Word格式文档,以方便收藏与打印。