The 2023 ICPC Asia Jinan Regional Contest (The 2nd Universal Cup. Stage 17: Jinan)
D. Largest Digit
題意:給定兩個範圍la, ra, lb, rb,求在兩個範圍內選任意兩個數相加,求最大的數位
思路:暴力列舉即可,遇到9跳出迴圈
void solve(){ ll la, ra, lb, rb; cin >> la >> ra >> lb >> rb; ll ans = 0; for(ll i = la; i <= ra; i ++){ for(ll j = lb; j <= rb; j ++){ ll res = 0; ll u = i + j; while(u){ res = max(res, u % 10); u /= 10; } ans = max(ans, res); if(ans == 9) break; } if(ans == 9) break; } cout << ans << '\n'; }
I. Strange Sorting
題意:給定一個長度為 n 的排列,可以至多選擇⌊n / 2⌋個(l, r),並且 al < ar ,將(l, r)範圍內的數字按照升序排序,求將整個排列完成升序排序的一個方案
思路:每次找當前第一個 a[i]!=i 的數字然後找最後的 a[j]<a[i] 的數字,對這個區間進行排序,在給定的範圍內能完成排序
void solve(){ int n; cin >> n; vector<int> a(n + 1); for(int i = 1; i <= n; i ++) cin >> a[i]; vector<PII> ans; for(int i = 1; i <= n; i ++){ if(a[i] != i){ int p = i; for(int j = i + 1; j <= n; j ++){ if(a[j] < a[i]) p = j; } sort(a.begin() + i, a.begin() + p + 1); ans.push_back({i, p}); } } cout << ans.size() << '\n'; for(auto [x, y] : ans){ cout << x << ' ' << y << '\n'; } }
A. Many Many Heads
題意:給定一個括號序列,包含[]()這四種,你可以對括號進行左右變化任意次,但是不能改變括號的種類,問是否存在且僅存在一種合法的括號序列
思路:賽時和隊友想的做法是:先把當前的括號序列進行構造變成一個合法的括號序列,然後進行判斷每對括號內是否存在兩對相同型別的括號序列在同一深度
深度的定義:例如這樣的括號序列 ([])([]),我們對他們進行編號:1,2,3,4,5,6,7,8,那麼1,4,5,8的括號位於0深度,2,3,6,7括號的深度為1
如果存在同樣深度的兩對括號,例如(.......)(......)那麼這兩對括號一定能夠組成另外一種合法的情況
那麼為什麼一定會出現這種情況呢?這和一開始我們構造的方法有關係:我們定義一個儲存符號的陣列 a,當a為空,我們把第一個放入的括號都變成向右的括號,然後檢測之後加入的括號型別,如果是型別相同的括號就配對為一對,否則加入對應型別的向右的括號,所以同一層內只要合法是不會出現(())這種的情況
然後接下來就是:對深度進行檢測,如果當前同一深度的不存在相同的,就把這一層清空,因為後面有可能還會進入這個深度
void solve(){ string s, s1; cin >> s; vector<char> a; for(int i = 0; i < s.size(); i ++){ if(a.size() == 0){ if(s[i] == '(' || s[i] == ')'){ a.push_back('('); s1 += '('; } else{ a.push_back('['); s1 += '['; } }//空先放左括號 else{ if(a.back() == '('){ if(s[i] == '(' || s[i] == ')'){ s1 += ")"; a.pop_back(); } else{ a.push_back('['); s1 += '['; } } else if(a.back() == '['){ if(s[i] == '[' || s[i] == ']'){ s1 += "]"; a.pop_back(); } else{ a.push_back('('); s1 += '('; } } }//對應匹配 } int p = 0, q = 0;//記錄當前深度 map<int, int> x, y; //x是圓括號的深度,y是方括號的深度 for(auto c:s1) { if(c == '(') p ++; else if(c == '[') q ++;//左邊界出現,當前深度++ else if(c == ')'){ x[q] ++; if(x[q] >= 2){ cout << "No\n"; return; }//對應深度出現了兩對 y[p] = 0;//這個深度合法就要清空 p --;//回到上一個深度 } else if(c == ']'){ y[p] ++; if(y[p] >= 2){ cout << "No\n"; return; } x[q] = 0; q --; } } cout << "Yes\n"; }
補題:正解很簡單,判斷三個連續相同的和兩個以上長度大於等於2的連續段會造成多種結果即可
void solve() { string s; cin >> s; int a = 0; int n = s.size(); for(int i = 0; i < n; i ++){ if(s[i] == ')') s[i] = '('; if(s[i] == ']') s[i] = '['; } for(int i = 0; i < n; i ++){ if(s[i + 1] == s[i]){ int res = 1; while(s[i + 1] == s[i]){ i ++; res ++; } if(res >= 3){ cout << "No\n"; return; } else a ++; } } if(a >= 3) cout << "No\n"; else cout << "Yes\n"; }
pending......