這題唯一的難點是要找區間裡最小的數,其他都很簡單。
可以暴力地用能夠 RMQ 的資料結構來做,時間是
把
#include <bits/stdc++.h>
#define StarBurstStream ios_base::sync_with_stdio(false); cin.tie(0);
#define iter(a) a.begin(), a.end()
using namespace std;
typedef long long ll;
int n;
vector<int> a, p;
vector<ll> s;
int np = 0;
int f(int l, int r){
if(l == r) return a[l];
while(p[np] < l || r < p[np]) np++;
int m = p[np];
if(s[m - 1] - s[l - 1] > s[r] - s[m]){
return f(l, m - 1);
}
else{
return f(m + 1, r);
}
}
int main(){
StarBurstStream
cin >> n;
a.resize(n + 1);
p.resize(n);
s.resize(n + 1);
for(int i = 1; i <= n; i++){
cin >> a[i];
s[i] = s[i - 1] + a[i];
p[i - 1] = i;
}
sort(iter(p), [](int u, int v){
return a[u] < a[v];
});
cout << f(1, n) << "\n";
return 0;
}
(感謝 dreamoon 在某篇貼文下的留言讓我想到有這個作法)
Cartesian Tree 定義:
一個數字皆相異的序列的 Cartesian Tree 是一個有 個節點的數,每個節點上都有一個值,根節點的值為 ,若這個值是 ,則左子樹為 的 Cartesian Tree、右子樹為 的 Cartesian Tree。空序列的 Cartesian Tree 定義為空樹。
可以發現到,題目的
區間和可以邊蓋 Cartesian Tree 邊算。
#include <bits/stdc++.h>
#define StarBurstStream ios_base::sync_with_stdio(false); cin.tie(0);
using namespace std;
typedef long long ll;
int n;
vector<int> a;
vector<ll> s;
vector<int> l, r; // 左右子節點
int f(int now){
if(l[now] == 0 && r[now] == 0) return a[now];
if(s[l[now]] > s[r[now]]) return f(l[now]);
else return f(r[now]);
}
int main(){
StarBurstStream
cin >> n;
a.resize(n + 1);
s.resize(n + 1);
l.resize(n + 1);
r.resize(n + 1);
stack<int> st;
for(int i = 1; i <= n; i++){
cin >> a[i];
s[i] = a[i];
int lst = 0;
while(!st.empty() && a[st.top()] > a[i]){
lst = st.top();
st.pop();
s[lst] += s[r[lst]];
}
if(!st.empty()){
r[st.top()] = i;
}
st.push(i);
l[i] = lst;
s[i] += s[lst];
}
int root;
while(!st.empty()){
root = st.top();
s[root] += s[r[root]];
st.pop();
}
cout << f(root) << "\n";
return 0;
}
應該是不會有人想要在考試中寫這個
定義如果一個區間當中沒有重複數字,則它是一個合法區間。
肯定有一個最佳解滿足其中每一個肯定滿足其中任兩個區間不相交,首先,當然不會有區間完全包含另一個區間,否則只要留下比較大的那個就好了,如果有兩個區間
所以我們只要考慮所有區間都不重疊的狀況,令
也就是在
令
所以目標就是在
計算
#include <bits/stdc++.h>
#define StarBurstStream ios_base::sync_with_stdio(false); cin.tie(0);
#define eb(a) emplace_back(a)
#define pob pop_back()
#define pof pop_front()
#define mp(a, b) make_pair(a, b)
#define F first
#define S second
using namespace std;
using pii = pair<int, int>;
int main(){
StarBurstStream
int n, k;
cin >> n >> k;
vector<int> a(n + 1);
for(int i = 1; i <= n; i++) cin >> a[i];
vector<int> lst(100001, -1);
vector<int> t(n + 1);
int now = 0;
for(int i = 1; i <= n; i++){
if(lst[a[i]] != -1) now = max(now, lst[a[i]]);
t[i] = now + 1;
lst[a[i]] = i;
}
vector<vector<int>> dp(k + 1, vector<int>(n + 1));
for(int i = 1; i <= k; i++){
deque<pii> dq;
for(int j = 1; j <= n; j++){
while(!dq.empty() && dq.front().S < t[j]) dq.pof;
while(!dq.empty() && dq.back().F <= dp[i - 1][j - 1] - j) dq.pob;
dq.eb(mp(dp[i - 1][j - 1] - j, j));
dp[i][j] = max(dp[i][j - 1], j + 1 + dq.front().F);
}
}
cout << dp[k][n] << "\n";
return 0;
}
競賽連結請先登入 Codeforces 帳號再點擊。 附中校內賽 時間:2022-10-08(六) 14:00-17:00 OI 制,6 題 不可使用電子、紙本參考資料(cppreference 除外) 無計分板 競賽連結:Codeforces 題本
Oct 10, 2022粉絲專頁:師大附中/延平中學 競技程式讀書會 活動簡介 最近幾年,資訊相關科系成為了熱門科系,也越來越多人參加 APCS 和各種資訊競賽。在高中,最主流的資訊競賽是演算法競賽,或者叫競技程式。 資訊作為一個非主科的科目,相對於數學、地科等等科目,資源少了很多,也比較難以入門。因此,附中和延平的一些有經驗的競賽選手自發舉辦了這個讀書會,旨在提供長期、完整的競賽課程,讓每個人都有機會接受良好的競賽指導,並且促進選手之間的交流,提升兩校的競賽風氣。 活動內容 讀書會的活動以上課為主,預計從 110 學年度上學期開學後開始上課,時間暫定為每週四 18:30 至 21:30,段考前一週停課。上學期會教基本的競賽知識,下學期則是較進階的技巧,且上下學期的期中、期末會各有一次模擬競賽。
Jun 30, 2022時間:2021-10-03 14:00-17:00 三個小時,OI 制,賽中沒計分板 競賽連結:110 學年度 師大附中資訊學科能力競賽 上機 Mirror (請先登入 Codeforces 再點連結) 題解:https://hackmd.io/@joylintp/r1ad59CQK
Oct 3, 2021因為不小心出太難了,場內沒幾個人寫得出來,所以丟出來給大家打 (?)。 共兩場,一場三個小時,OI 制,語言限 C/C++。 時間 模擬競賽 I:2021/09/20(一) 14:00-17:00 模擬競賽 II:2021/09/21(二) 14:00-17:00 比賽連結 在 Codeforces 上比,請先登入 Codeforces 再點擊以下連結。
Sep 21, 2021or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up