字符串匹配

题意:给出一个字符串,只有 ( ) 这两种,有三种操作

             1、query查找一段字符里的括号是否匹配

             2、set一段字符为某一种

             3、reverse  把一段中的括号都变为其反


解法:用1表示该位置的'(' ,-1表示')'

          线段树中的重要变量sum-和,lmin该段所有前缀中最小和,lmax前缀中最大和,br记录reverse的次数

         t[cur].sum=t[lson].sum+t[rson].sum;

         t[cur].lmin=min(t[lson].lmin,t[rson].lmin+t[lson].sum);

         t[cur].lmax=max(t[lson].lmax,t[son].lmax+t[lson].sum);


注意:向下更新的顺序,。。应该把reverse的更新优先。不然可能重复更新。。

           这个让我WA苦了。



#include<iostream>
#include<cstdio>
#include<cstdlib>

using namespace std;
#define N 101000

struct tree
{
	int left,right;
	int lmax,lmin;
	int mid;
	int len;
	int sum;
	int br;
}t[4*N];
int n,q;
int small;
int sum;
char str[N];

void build(int cur,int l,int r)
{
	t[cur].left=l;
	t[cur].br=0;
	t[cur].right=r;
	t[cur].mid=(l+r)>>1;
	t[cur].len=r-l+1;
	if (l==r)
	{
		if (str[l]=='(')
		{
			t[cur].sum=1;
			t[cur].lmax=1;
			t[cur].lmin=1;

		}
		else
		{
			t[cur].sum=-1;
			t[cur].lmax=-1;
			t[cur].lmin=-1;
		}
	}
	else
	{
		int L=cur<<1,R=cur<<1|1;
		build(L,l,t[cur].mid);
		build(R,t[cur].mid+1,r);
		t[cur].sum=t[L].sum+t[R].sum;
		t[cur].lmin=min(t[L].lmin,t[R].lmin+t[L].sum);
		t[cur].lmax=max(t[L].lmax,t[R].lmax+t[L].sum);
	}
}

void update(int cur,int l,int r,int v)
{
	if (l==t[cur].left && r==t[cur].right)
	{
		if (v==1)
		{
		    t[cur].lmax=t[cur].sum=t[cur].len;
		    t[cur].lmin=1;
		}
		else
		{
		    t[cur].lmin=t[cur].sum=-t[cur].len;
		    t[cur].lmax=-1;
		}
		return ;
	}
	int L=cur<<1,R=cur<<1|1;


    if (t[cur].br&1)
	{
		t[cur].br++;
		t[L].br++;
		t[R].br++;
		t[L].sum=-t[L].sum;
		t[R].sum=-t[R].sum;
		int temp=-t[L].lmin;
		t[L].lmin=-t[L].lmax;
		t[L].lmax=temp;
		temp=-t[R].lmin;
		t[R].lmin=-t[R].lmax;
		t[R].lmax=temp;
	}
	if (t[cur].len==t[cur].sum)
	{
		t[L].lmax=t[L].sum=t[L].len;
		t[L].lmin=1;
		t[R].lmax=t[R].sum=t[R].len;
		t[R].lmin=1;
	}
	if (t[cur].len==-t[cur].sum)
	{
		t[L].lmin=t[L].sum=-t[L].len;
		t[R].lmin=t[R].sum=-t[R].len;
		t[L].lmax=-1;
		t[R].lmax=-1;
	}

	int m=t[cur].mid;
	if (r<=m)
		update(L,l,r,v);
	else if (l>m)
		update(R,l,r,v);
	else
	{
		update(L,l,m,v);
		update(R,m+1,r,v);
	}
	t[cur].sum=t[L].sum+t[R].sum;
	t[cur].lmin=min(t[L].lmin,t[R].lmin+t[L].sum);
	t[cur].lmax=max(t[L].lmax,t[R].lmax+t[L].sum);
}

void reverse(int cur,int l,int r)
{
      //  cout<<cur<<' '<<t[cur].left<<' '<<t[cur].right<<' '<<t[cur].sum<<' '<<t[cur].lmin<<' '<<t[cur].lmax<<' '<<l<<' '<<r
    //    <<' '<<t[cur].br<<' '<<t[cur].len<<endl;
	if (l==t[cur].left && r==t[cur].right)
	{

		t[cur].sum=-t[cur].sum;

		int tt=-t[cur].lmax;
		t[cur].lmax=-t[cur].lmin;
		t[cur].lmin=tt;
		t[cur].br++;
		return ;
	}
	int L=cur<<1,R=cur<<1|1;
	if (t[cur].br&1)
	{

		t[cur].br++;
		t[L].br++;
		t[R].br++;
		t[L].sum=-t[L].sum;
		t[R].sum=-t[R].sum;
		int temp=-t[L].lmin;
		t[L].lmin=-t[L].lmax;
		t[L].lmax=temp;
		temp=-t[R].lmin;
		t[R].lmin=-t[R].lmax;
		t[R].lmax=temp;
	}
	if (t[cur].len==t[cur].sum)
	{
		t[L].lmax=t[L].sum=t[L].len;
		t[L].lmin=1;
		t[R].lmax=t[R].sum=t[R].len;
		t[R].lmin=1;
	}
	if (t[cur].len==-t[cur].sum)
	{
		t[L].lmin=t[L].sum=-t[L].len;
		t[R].lmin=t[R].sum=-t[R].len;
		t[L].lmax=-1;
		t[R].lmax=-1;
	}


	int m=t[cur].mid;
	if (r<=m)
		reverse(L,l,r);
	else if (l>m)
		reverse(R,l,r);
	else
	{
		reverse(L,l,m);
		reverse(R,m+1,r);
	}
	t[cur].sum=t[L].sum+t[R].sum;
	t[cur].lmin=min(t[L].lmin,t[R].lmin+t[L].sum);
	t[cur].lmax=max(t[L].lmax,t[R].lmax+t[L].sum);
}

void qurey(int cur,int l,int r)
{
  //  cout<<cur<<' '<<t[cur].left<<' '<<t[cur].right<<' '<<t[cur].sum<<' '<<t[cur].lmin<<' '<<t[cur].lmax<<' '<<l<<' '<<r
 //       <<' '<<t[cur].br<<' '<<t[cur].len<<endl;
	if (l==t[cur].left && r==t[cur].right)
	{
		small=min(small,sum+t[cur].lmin);
		sum+=t[cur].sum;
		return ;
	}
	int L=cur<<1,R=cur<<1|1;
	int m=t[cur].mid;

	if (t[cur].br&1)
	{
		t[cur].br++;
		t[L].br++;
		t[R].br++;
		t[L].sum=-t[L].sum;
		t[R].sum=-t[R].sum;
		int temp=-t[L].lmin;
		t[L].lmin=-t[L].lmax;
		t[L].lmax=temp;
		temp=-t[R].lmin;
		t[R].lmin=-t[R].lmax;
		t[R].lmax=temp;
	}

	if (t[cur].len==t[cur].sum)
	{
		t[L].lmax=t[L].sum=t[L].len;
		t[L].lmin=1;
		t[R].lmax=t[R].sum=t[R].len;
		t[R].lmin=1;
	}
	if (t[cur].len==-t[cur].sum)
	{
		t[L].lmin=t[L].sum=-t[L].len;
		t[R].lmin=t[R].sum=-t[R].len;
		t[L].lmax=-1;
		t[R].lmax=-1;
	}


	if (r<=m)
		qurey(L,l,r);
	else if (l>m)
		qurey(R,l,r);
	else
	{
		qurey(L,l,m);
		qurey(R,m+1,r);
	}

}

int main()
{
	freopen("in.txt","r",stdin);
	int i,j,k;
	int nc;
	char s[33];
	scanf("%d",&nc);

	int num=1;
	while (nc--)
	{
		scanf("%d%s",&n,str);
		scanf("%d",&q);

		printf("Case %d:\n",num++);
		build(1,0,n-1);
		while (q--)
		{

			scanf("%s",s);
			scanf("%d%d",&i,&j);
		//	cout<<s<<' '<<i<<' '<<j<<endl;
			if (s[0]=='q')
			{
				if ((j-i)&1)
				{

					sum=small=0;
					qurey(1,i,j);

			//		cout<<sum<<' '<<small<<endl;
					if (sum==0 && small>=0)
						printf("YES\n");
					else
						printf("NO\n");
				}
				else
					printf("NO\n");
			}
			else if (s[0]=='s')
			{
				scanf("%s",s);
				if (s[0]=='(')
					update(1,i,j,1);
				else
					update(1,i,j,-1);
			}
			else
			{
				reverse(1,i,j);
			}
		}
		printf("\n");
	}


	return 0;
}



Bracket Sequence

Time Limit: 3000 ms Memory Limit: 65536 kB Solved: 36 Tried: 311

Submit

Status

Best Solution

Back

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".





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值