题解:P15034 奇迹之地
题意简述
有一个长度为 \(n\) 的序列 \(a_1,a_2,\dots,a_n\)。每次操作,你可以钦定一个 \(k\),然后选择第一个 \(a_i\geq k\),令 \(a_i\gets a_i-k\),并获得 \(k\) 的收益,每次操作后 \(a_i\) 不能为 \(0\)。
思路分析
容易证明,\(k\) 的值一定是 \(a_i-1\),并且 \(a_i\) 之前没有出现过 \(\geq a_i-1\) 的数。
直接扫一遍序列,如果 \(a_i\) 满足条件,就取走它。显然这个操作对前面的数没有影响,所以不用回头搜索,时间复杂度 \(O(n)\)。
代码实现
Code
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, Max = 0;
cin >> n;
set<int> vis; long long ans = 0;
vis.insert(0);
for(int i = 1; i <= n; i++){
int x; cin >> x;
if(Max >= x) continue;
auto it = vis.find(x - 1);
if(it != vis.end()) vis.insert(x), Max = max(Max, x);
else ans += x - 1, Max = max(Max, 1), vis.insert(1);
}
cout << ans << '\n';
return 0;
}

浙公网安备 33010602011771号