【UR #2】猪猪侠再战括号序列

UOJ小清新题表

题目摘要

UOJ链接

有一个由 (n) 个左括号 “(” 和 (n) 个右括号 “)” 组成的序列。每次操作时可以选定两个数 (l,r),然后把第 (l) 到第 (r) 个括号的顺序翻转(括号的朝向保持不变)。例如将 “()((()(” 翻转第 (3) 到第 (7) 个括号后的结果为 “()()(((”。

我希望使用不超过 (n) 次操作,将这个序列变为一个合法的括号序列。

众所周知,合法括号序列的定义如下:

  • () 是合法括号序列;
  • 如果 A 是合法括号序列,则 (A) 是合法括号序列;
  • 如果 A,B 是合法括号序列,则 AB 是合法括号序列。

数据范围

(nleq 100000)

思路

GGBond!!!

难度:入门

由于新换的主题感觉很好看于是来水博客

显然最好的结构就是((())),由于题目保证有解,所以直接双指针 (O(n)) 扫一遍,遇到一个左括号就和左面第一个右括号(如果有)交换即可。可以证明一定是对的。

然后小坑就是字符串最大长度为 (2n),你要是开数组为 (10^5) 的话就 (RE) 了...

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int tot;
char s[maxn];
int L[maxn],R[maxn];

int main(){
    scanf("%s",s+1);
    int len=strlen(s+1);
    for(int i=1,j=1;i<=len;i++){
        if(s[i]=='('){
            while(j<i&&s[j]!=')')j++;
            if(i!=j){
                swap(s[i],s[j]);
                L[++tot]=j;R[tot]=i;
            }
        }
    }
    printf("%d
",tot);
    for(int i=1;i<=tot;i++)
        printf("%d %d
",L[i],R[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/Midoria7/p/13519972.html