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


    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≤2104)  — 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尽量小嘛?????????

  • 相关阅读:
    [转]狼的故事8:生存就是坚持
    [转]狼的故事7:单枪匹马的代价
    如何在GridView的Footer内显示总计?
    javascript中如何正确将日期(Date)字符串转换为日期(Date)对象?
    无限级分类(非递归算法/存储过程版/GUID主键)完整数据库示例_(1)表结构
    [转]狼的故事12:王者的风范
    [转]狼的故事2:光线背后的嚎叫
    vs.net2008正式版发布并提供下载(英文版)
    [转]狼的故事11:以牙还牙
    [转]狼的故事3:百分之百的死亡
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/16347602.html
Copyright © 2020-2023  润新知