2

The problem is:

  • Given the string with length of n, and m queries.

  • Each query is one of two cases:

    • Change the i-th character oppositely
    • Check if the substring from u-th character to v-th character is the correct brackets expression or not. If yes, print 1, else print 0.

Time limit: 0.2s

In these cases, a correct brackets expression is defined:

  • a string with length of 0

  • a string only contains '(' and ')'

  • if A is a correct brackets expression, then (A) is also a correct brackets expression

  • if A and B is correct brackets expressions, then AB is also a correct brackets expression

My main idea is similar to the problem 380C on CodeForces, http://codeforces.com/blog/entry/10363

Then I check if the longest subsequence in the given ranges is equal to the length of ranges, so I will get the answer. But I got time limit error.

I have been searching for this on the internet all day but I haven't got the answer. I will be grateful if you help me. :)

Here is my code: https://github.com/hoangvanthien/GH_CppFiles/blob/master/SPOJ/NKBRACKE.cpp

Pham Trung
  • 11,204
  • 2
  • 24
  • 43

1 Answers1

1

The conditions for a valid bracket sequence are:

  • Length of the substring is even.

  • The number of open and close brackets are equaled.

  • At any point in the sequence, there is no point which number of close brackets is greater than the number of open brackets.

So, from the original string of open and close brackets, we can convert it into sequence of number, each number represent the difference between open and close brackets from the beginning of the sequence. Each open brackets, we will plus one, and minus one for close.

For example, for ((())))) -> we have the sequence { 1, 2 , 3, 2 , 1, 0, -1, -2 }

So, to test if a substring is valid, for example, substring (2, 5), which is ())), we need to see if at any point, the difference between open and close is negative. From above sequence, we have {3, 2, 1, 0}, and we need to minus 2 for each element, as we need to remove those brackets from the beginning of the string, which are not in the substring. -> we have {1, 0, -1, -2} -> so the substring is invalid.

After understand above idea, we can have our solution for the problem.

  • What we need is a data structure, which can quickly update a range. For example, if we change from ( to ) at index 3, so we need to minus -2 to all element from index 3 onward.

  • And we need the data structure to quickly return the minimum value of a range (we only need to care about minimum value).

And from all of that requirements, we can use a Segment tree, which give you O(log n) update and O(log n) retrieve.

Pseudo code

SegmentTree tree;

Initialize the tree with original sequence

for each query in the tree
   if( query type is update)
      if(change from ) to ()
         increase all value by 2 from range index to n
      else if(change from ( to ) )
         decrease all value by 2 from range index to n
   else
      int min = tree.getMinimumValueInRange(u, v)
      int notInSubstring = tree.getMinimumValueInRange(u - 1, u - 1)
      if(min - notInSubstring < 0)
          print Invalid 
      else if( length of substring is not even)
          print Invalid
      else if( tree.getMinimumValueInRange(v, v) != notInSubstring)//Number of open and close brackets are not equaled.
          print Invalid
Pham Trung
  • 11,204
  • 2
  • 24
  • 43
  • Creative! But my solution is also O(log n) update, and O(log n) retrieve, still time limit exceeded. The limited time is 0.2 seconds. – Hoang Van Thien Dec 17 '15 at 05:01
  • @HoangVanThien Segment tree is correct approach, maybe you can try to optimize your solution by using array, instead of using struct `Node` as in your current implementation. And considering change the return type of `getLength` from Node to int if applicable can also give you some performance boost. – Pham Trung Dec 17 '15 at 05:24