【UR #2】豬豬俠再戰括號序列
阿新 • • 發佈:2020-08-17
UOJ小清新題表
題目摘要
有一個由 \(n\) 個左括號 “(
” 和 \(n\) 個右括號 “)
” 組成的序列。每次操作時可以選定兩個數 \(l,r\),然後把第 \(l\) 到第 \(r\) 個括號的順序翻轉(括號的朝向保持不變)。例如將 “()((()(
” 翻轉第 \(3\) 到第 \(7\) 個括號後的結果為 “()()(((
”。
我希望使用不超過 \(n\) 次操作,將這個序列變為一個合法的括號序列。
眾所周知,合法括號序列的定義如下:
()
是合法括號序列;- 如果
A
是合法括號序列,則(A)
是合法括號序列; - 如果
A,B
是合法括號序列,則AB
是合法括號序列。
資料範圍
\(n\leq 100000\)
思路
難度:入門
由於新換的主題感覺很好看於是來水部落格
顯然最好的結構就是((()))
,由於題目保證有解,所以直接雙指標 \(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\n",tot); for(int i=1;i<=tot;i++) printf("%d %d\n",L[i],R[i]); return 0; }