AtCoder Regular Contest 133 題解
\(A\) 題 \(Erase\) \(by\) \(Value\)
給定一個長度為 \(n\) 的數列,你可以確定一個數 \(x\) ,從中刪去所有值為 \(x\) 的數,使得剩下的數列字典序最小。
\(1 \le n \le 200000\)
難度評分 \(265\) ,簡單貪心題。
字典序最小,等價于越靠前的數字越小,所以在從前往後考慮時,就不必考慮當前位置後面的數字,考慮數列中相鄰的兩個數
\(a_i,a_{i+1}\) , 如果 \(a_i > a_{i+1}\) ,那麼 \(a_{i+1}\) 排在前面必然比排在後面字典序小,這時如果還有刪除次數,那麼就刪除
\(a_i\) 對應的所有數,必然使得字典序最小,正確性顯然,時間複雜度 \(O(n)\)
\(B\) 題 \(Dividing\) \(Subsequence\)
給定兩個長度為 \(n\) 的排列 \(P,Q\) ,從兩排列中選出下標相同的子序列,使得 \(Q\) 中選出的子序列的每一項都是 \(P\) 中選出的子序列對應那一項的倍數,求這樣的最長序列長度。
\(1 \le n \le 200000\)
難度評分 \(1315\) ,比上一題難了幾個檔次,但其實還是比較套路的題目。
這題我開始的想法是,把 \(P\) 中的數字下標向 \(Q\) 中對應的數字的倍數的下標想成區間,也可以理解為連一條邊,這樣就轉化為了從一些區間中取出一些區間,使得剩下區間兩兩交集為空的最大區間數,這是一個經典的貪心問題。
但這樣做存在一些問題,比如由後向前的對應和由前向後的對應不好區分,於是考慮換個思路。
其實這題是一道叫做友好城市的題目的擴充套件題,有興趣的可以去了解。
求最長的序列長度,自然也會想到求 \(LIS\) ,在這個問題中,如果不把之前位置間的對應想成區間,而是想成一個數對,那麼形式化地,有如下轉化:
有數對 \((i_1,j_1),(i_2,j_2)......(i_k,j_k)\) 這麼一些數對,選出最多的數對,使得選出的數對 \(i,j\) 都單調遞增。
這種問題的一類通用解法是(包括友好城市那題也是如此),按照一維排序,剩下的一維求最長上升子序列。
但此處 \(i,j\) 都是有重複數字的,如果只單純的按 \(i\)
時間複雜度 \(O(nlogn)\) 。