ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

E. Bring Balance (括号匹配问题+贪心+前缀和)(CF 794 d2)

2022-06-06 11:32:37  阅读:157  来源: 互联网

标签:794 前缀 sequence CF balanced Bring test ri string


E. Bring Balance
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Alina has a bracket sequence s of length 2n, consisting of n opening brackets '(' and n closing brackets ')'. As she likes balance, she wants to turn this bracket sequence into a balanced bracket sequence.

In one operation, she can reverse any substring of s.

What's the smallest number of operations that she needs to turn s into a balanced bracket sequence? It can be shown that it's always possible in at most n operations.

As a reminder, a sequence of brackets is called balanced if one can turn it into a valid math expression by adding characters + and 1. For example, sequences (())(), (), and (()(())) are balanced, while )(, ((), and (()))( are not.

Input
The first line of the input contains a single integer t (1≤t≤2⋅104)  — the number of test cases. The description of the test cases follows.

The first line of each test case contains a single integer n (1≤n≤105).

The second line of each test case contains a string s of length 2n, consisting of n opening and n closing brackets.

The sum of n over all test cases doesn't exceed 2⋅105.

Output
For each test case, in the first line output a single integer k (0≤k≤n)  — the smallest number of operations required.

The i-th of the next k lines should contain two integers li,ri (1≤li≤ri≤2n), indicating that in the i-th operation, Alina will reverse the substring slsl+1…sr−1sr. Here the numeration starts from 1.

If there are multiple sequences of operations with the smallest length which transform the sequence into a balanced one, you can output any of them.

Example
inputCopy
3
2
(())
5
())((()))(
6
())((()))(()
outputCopy
0
2
3 4
9 10
1
2 11
Note
In the first test case, the string is already balanced.

In the second test case, the string will be transformed as follows: ())((()))( → ()()(()))( → ()()(())(), where the last string is balanced.

In the third test case, the string will be transformed to ((()))((())), which is balanced.
View problem

思路:

  • 核心: 把 ‘(’ 弄成 1,  ‘)’弄成 -1;,在利用前缀和, 画出前缀和的图像,
  • 前缀和为0的点就是刚刚匹配好, 出现<0的点 就代表这个数列不合规了
  • reverse 这个 某一段 就是把趋势对调,- + - + 变成 + - + -, L-1的值和 R的,值还是不变 (注意不是R+1)(前缀和嘛)
  • 于是对于起点-1和终点值一样的reverse 就是相当于前缀和图像向上面对翻
  • 本题:
  • 结论 1 , 最多2 次就可以把 这个数列搞合格 (本题 n个1和n个-1) ,n>>=1;
  • reverse 1- x, x+1,n (x,前缀和最大的那个点)
  • 贪心简要推: 1-X 先把 上升趋势给他搞上去,之后不管怎么变 都不会小于0,(Codeforce 有严格推论)
  • X+1 - n, 把下降的尽量往后边放.
  • 所以 只需要在判读 0,1步骤有没有
  • 0,就直接判断就行了 arr[i]>=0;
  • 1, 首先找到 L ,R 把所有的小于0的点包裹进去
  • 然后让 L 变成 max(arr[1]-arr[L])的点 贪心思想: 让前面的值(起点)尽量大,为后面提供容错,下降趋势往后面衍生,
  • R 也是选一个后面的最大值, 贪心思想: 让一个尽量大的上升趋势往前面排.
  • 注意具体操作时的 节点问题 , L 和R 有点区别的. L要+1,(i=0开始,防止 l=1,还要+1,(L要=1)) (一开始就下降的时候)
#include <bits/stdc++.h>
using namespace std;
#define M 400005
#define ri register int 

template <class G> void read(G &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return ;
}


int t;
int n;
long long arr[M];
int main(){
    ios::sync_with_stdio(false);
  cin.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>n;
        n*=2;
        string s;
        cin>>s;
        vector<int>p(n+1);
        int mx=1;
        for(ri i=0;i<s.length();i++)
        {
            if(s[i]=='(') p[i+1]=1;
            else p[i+1]=-1;
            arr[i+1]=arr[i]+p[i+1];
            if(arr[mx]<arr[i+1]) mx=i+1;
        }
        int flag=1;
        for(ri i=1;i<=n;i++)
        {
            if(arr[i]<0) 
            {
                flag=0;break;
            }
        }
        if(flag)
        {
            printf("0\n");
            continue;
        }
        int l=0,r=0;
        for(ri i=1;i<=n;i++)
        {
            if(arr[i]<0)
            {
                l=i; break; 
            }
        }
        for(ri i=n;i>=1;i--)
        {
            if(arr[i]<0)
            {
                r=i; break; 
            }
        }
        r++;
        int tmp=l;
        for(ri i=0;i<=tmp;i++)
        {
            if(arr[i]>arr[l]) l=i;
        }
        tmp=r;
        for(ri i=tmp+1;i<=n;i++)
        {
            if(arr[i]>arr[r]) r=i;
        }
        l++;
        reverse(s.begin()+l-1,s.begin()+r+1-1);
        flag=1;
        for(ri i=0;i<s.length();i++)
        {
            if(s[i]=='(') p[i+1]=1;
            else p[i+1]=-1;
            arr[i+1]=arr[i]+p[i+1];
            if(arr[i+1]<0) 
            {
                flag=0;break;
            }
        }
        if(flag)
        {
            printf("1\n");
            printf("%d %d\n",l,r);
            continue;
        }
        printf("2\n");
        printf("1 %d %d %d\n",mx,mx+1,n);
    }
    return 0;
    
} 
View Code

最后小声BB,他题目还要要求L,R尽量小嘛?????????

标签:794,前缀,sequence,CF,balanced,Bring,test,ri,string
来源: https://www.cnblogs.com/Lamboofhome/p/16347602.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有