今天好开心,印象中应该是第一次自己开出了的题,显然我太菜了。。。
当然写之前我也不知道这是的题,我就感觉很有意思。 然后接下来我将记录下写这道题的全部心路历程。(我很菜,大佬轻点骂)。
分析
首先,我看到这个题第一想法就是,之前打多了,发现很多这种难度的思维题都是,我当时考虑的是记录走到第天的最大值,但是很快发现,被暴打了,首先就算不考虑天,光这个时间复杂度就要,这不是扯淡吗?,然后加上一个,直接,你fp呢,这复杂度过nm呢,于是排除了这个想法,然后又想到了空间换时间表示走到第天时候选了天的最大值,然后显然不行,直接内存超限了。然后就是还想到了状态,只取分别表示拿还是不拿,但是这样也仅仅把时间复杂度降到了,还是过不去,正当我想去看题解的时候,突然————————————————————————————————————————
我发现了一个点,也就是这个点让我突破了这个题,就是我们其实对于的考虑只需要考虑什么呢?只需要考虑我们最后一次取数在第几天,因为无论我们前面怎么取(就算什么都不取),我们最后也是在要减去,其中为最后取的那一天。于是其实我们要比较的就是最后在哪一天取的时候我们再减去得到的值最大即可,于是我们很显然至少要把序列枚举一遍也就是,而的话显然不行,因为我们还有维,所以这个时候我就发现这个题其实是个贪心,然后这时我就在想,应该怎么考虑这个数呢,或者是个数?我就想到了可以用一个大根堆来维护,首先如果这个数比小,我们显然不要放进去,因为不选都是,也比他大,然后对于我们遍历到的每个,如果堆的大小的话,我们就把这个数塞进去,如果的时候,我们就看堆顶元素,要是这个,那么我们就执行操作,然后让这个数入堆,再在这个过程中维护一个来记录每次的最大值,然后每次遍历结束,我们更新一下即可,记好开,然后这个题我们就完美的解决啦!然后一发过样例一发过了这题很快的啊!!!时间复杂度。
代码
#include <bits/stdc++.h>
#define ll long long
#define x first
#define y second
using namespace std;
const int N=200010;
int t;
priority_queue<ll,vector<ll>,greater<ll>> heap;
ll n,m,d;//n天m场电影d差值
ll a[N];//a[i]表示值
void solve(){
while(heap.size()){
int to=heap.top();
heap.pop();
}
ll ans=0,res=0;
cin>>n>>m>>d;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
if(a[i]>0){
int si=heap.size();
if(si<m){
heap.push(a[i]);
res+=a[i];
}
else if(si==m){
ll to=heap.top();
if(a[i]>to){
heap.pop();
heap.push(a[i]);
res+=a[i];
res-=to;
}
}
}
ll temp=res-i*d;
ans=max(ans,temp);
}
cout<<ans<<"\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin>>t;
while(t--) solve();
return 0;
}
加油嘞!