zoukankan      html  css  js  c++  java
  • Flipping Parentheses~Gym 100803G

    Description

    A string consisting only of parentheses ‘(’ and ‘)’ is called balanced if it is one of the following.

    • A string “()” is balanced.
    • Concatenation of two balanced strings are balanced.
    • When a string s is balanced, so is the concatenation of three strings “(”, s, and “)” in this order.

    Note that the condition is stronger than merely the numbers of ‘(’ and ‘)’ are equal. For instance, “())(()” is not balanced.

    Your task is to keep a string in a balanced state, under a severe condition in which a cosmic ray may flip the direction of parentheses.

    You are initially given a balanced string. Each time the direction of a single parenthesis is flipped, your program is notified the position of the changed character in the string. Then, calculate and output the leftmost position that, if the parenthesis there is flipped, the whole string gets back to the balanced state. After the string is balanced by changing the parenthesis indicated by your program, next cosmic ray flips another parenthesis, and the steps are repeated several times.

    Input

    The input consists of a single test case formatted as follows. 

    N Qsq1qQN Qsq1⋮qQ

    The first line consists of two integers N and Q (2 ≤ N ≤ 300000, 1 ≤ Q ≤ 150000). The second line is a string s of balanced parentheses with length N. Each of the following Q lines is an integer qi (1 ≤ qi ≤ N) that indicates that the direction of the qi-th parenthesis is flipped.

    Output

    For each event qi, output the position of the leftmost parenthesis you need to flip in order to get back to the balanced state.

    Note that each input flipping event qi is applied to the string after the previous flip qi − 1 and its fix.

    Sample Input

    6 3
    ((()))
    4
    3
    1
    
    20 9
    ()((((()))))()()()()
    15
    20
    13
    5
    3
    10
    3
    17
    18

    Sample Output

    2
    2
    1
    2
    20
    8
    5
    3
    2
    2
    3
    18

    Hint

    In the first sample, the initial state is “((()))”. The 4th parenthesis is flipped and the string becomes “(((())”. Then, to keep the balance you should flip the 2nd parenthesis and get “()(())”. The next flip of the 3rd parenthesis is applied to the last state and yields “())())”. To rebalance it, you have to change the 2nd parenthesis again yielding “(()())”.

    这题简直爆炸,知道感觉需要用线段树维护,但是不知道查询,而且我线段树血都写不出了

    好久好久没有写过线段树了,板子都不会了, 更别说应用了。

    题意:就是给你一个匹配好的括号串长度为n,在给你m个操作,每个操作就给翻转摸一个位置的括号,

    对于每一个操作,你要找到一括号将其翻转,使得最后这个串还是匹配的,

    若存在多个解,翻转最左边的那个括号。

     ( 为 1,   )为-1 ,然后容易联想到前缀和,

      然后就是用线段树去维护这个前缀和,

       如果是  x = )  就是找到第一个 ) 这个相对简单 ,用set和线段树都可以做

       如果是 x = ( 就是从左到右 找到第一个 ( 这个就只能用线段树实现了

      记录了前缀和,其实只要找到一段区间的最小值都大于1就行了;

      这个就是整个线段树最难的部分了,

      int query1(int rt, int L, int R) {
            if (L == R) return L + 1;
            int mid = (L + R) >> 1;
            pushdown(rt);
            if (tree[rt << 1 | 1].r < 2 ) query1(rt << 1 | 1, mid + 1, R);
            else query1(rt << 1, L, mid);

      }

      当时的我怎么也想不出。 太菜了;

      注意每一个找到了y  记得更新 y 

      

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 using namespace std;
     6 const int maxn = 3e5 + 10;
     7 char s[maxn];
     8 int  sum[maxn];
     9 struct node {
    10     int l, r, add;
    11 } tree[maxn * 4];
    12 int fun(int i) {
    13     return s[i] == '(' ? 1 : -1;
    14 }
    15 void pushup(int rt) {
    16     tree[rt].l = min(tree[rt << 1 | 1].l, tree[rt << 1].l);
    17     tree[rt].r = min(tree[rt << 1 | 1].r, tree[rt << 1].r);
    18 }
    19 void pushdown(int rt) {
    20     tree[rt << 1].l       += tree[rt].add;
    21     tree[rt << 1].r       += tree[rt].add;
    22     tree[rt << 1].add     += tree[rt].add;
    23     tree[rt << 1 | 1].l   += tree[rt].add;
    24     tree[rt << 1 | 1].r   += tree[rt].add;
    25     tree[rt << 1 | 1].add += tree[rt].add;
    26     tree[rt].add = 0;
    27 }
    28 void build(int rt, int L, int R) {
    29     tree[rt].add = 0;
    30     if (L == R) {
    31         tree[rt].l = sum[L] - L;
    32         tree[rt].r = sum[L];
    33         return ;
    34     }
    35     int mid = (L + R) >> 1;
    36     build(rt << 1, L, mid);
    37     build(rt << 1 | 1, mid + 1, R );
    38     pushup(rt);
    39 }
    40 void updata(int rt, int L, int R, int x, int add) {
    41     if (x <= L) {
    42         tree[rt].add += add;
    43         tree[rt].l  += add;
    44         tree[rt].r  += add;
    45         return ;
    46     }
    47     pushdown(rt);
    48     int mid = (L + R) >> 1;
    49     if (x <= mid) updata(rt << 1, L, mid, x, add);
    50     updata(rt << 1 | 1, mid + 1, R, x, add);
    51     pushup(rt);
    52 }
    53 int query1(int rt, int L, int R) {
    54     if (L == R) return L  + 1;
    55     int mid = (L + R) >> 1;
    56     pushdown(rt);
    57     if (tree[rt << 1 | 1].r < 2 ) query1(rt << 1 | 1, mid + 1, R);
    58     else query1(rt << 1, L, mid);
    59 }
    60 int query2(int rt, int L, int R) {
    61     if (L == R )  return L;
    62     int mid = (L + R) / 2;
    63     pushdown(rt);
    64     if (tree[rt << 1].l < 0 ) query2(rt << 1, L, mid);
    65     else query2((rt << 1) + 1, mid + 1, R) ;
    66 }
    67 
    68 int main() {
    69     int n, q, len, x, y;
    70     while(scanf("%d%d", &n, &q) != EOF) {
    71         s[0] = '0';
    72         memset(sum, 0, sizeof(sum));
    73         scanf("%s", s + 1);
    74         len = strlen(s) - 1;
    75         for (int i = 1 ; i <= len ; i++)
    76             sum[i] = sum[i - 1] + fun(i);
    77         build(1, 1, len);
    78         for (int i = 1 ; i <= q ; i++) {
    79             scanf("%d", &x);
    80             s[x] = (s[x] == '(' ? ')' : '(');
    81 
    82             if (s[x] == ')') updata(1, 1, len, x, -2);
    83             else updata(1, 1, len, x, 2);
    84 
    85             if (s[x] == ')') y = query2(1, 1, len);
    86             else y = query1(1, 1, len);
    87             s[y] = (s[y] == '(' ? ')' : '(' );
    88             if (s[y]=='(') updata(1,1,len,y,2);
    89             else updata(1,1,len,y,-2);
    90             printf("%d
    ", y);
    91 
    92         }
    93 
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    H5前端上传文件的几个解决方案
    MyEclipse和Eclipse各个版本的汉化破解(包括7.59.0和Eclips的ehelios、indigo各版本)
    学习C#中的事件和委托
    JS学习笔记(一)JS处理JSON数据
    图解Eclipse开发C++、C语言的配置过程使用CDT和MinGw
    ASP.NET使用C#实现的最简单的验证码方法
    微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结
    PHP开发笔记(二)PHP的json_encode和json_decode问题
    C博客作业00——我的第一篇博客
    extern "c"
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/9007741.html
Copyright © 2011-2022 走看看