【牛客】队列-蚯蚓(题解+学习笔记)

https://ac.nowcoder.com/acm/problem/16430
这是一道比较***钻的模拟题,一开始拿到题目直接开始优先队列模拟,一波操作猛如虎,最后发现每次切后忘了给每个元素加上q,而且切掉的是不加的。这就有点难受
但是如果我们换一种思路,因为是每秒切一刀,也就是每过一秒就加q。那我们不妨假设每次都加上,如果被切了就减一下。
而且也不用遍历加,因为加的多少是关于时间的一个函数,我们直接加需要操作的那些就行,因此我们需要三个队列,一个记录原始数据,另外两个记录被切下来的部分。
记录原始数据当然不用想,肯定用优先队列,但是剩下的两个不用,为什么呢?
先看代码

#include <bits/stdc++.h>
using namespace std;
int n,m,q,u,v,t;
priority_queue<int>q1;//记录原始数据
queue<int>q2,q3;//记录被切下来的部分
long long max_len(int t){//返回在t时刻所有蚯蚓长度最大值
    int x1,x2,x3; x1=x2=x3=-1;
    if(!q1.empty()) x1=q1.top()+t*q;
    if(!q2.empty()) x2=q2.front()+t*q;
    if(!q3.empty()) x3=q3.front()+t*q;
    if(x1>=x2&&x1>=x3){q1.pop();return x1;}//每找到一个最大值就操作一次
    else if(x2>=x1&&x2>=x3){q2.pop();return x2;}
    else {q3.pop();return x3;}
}
int main(){
    cin>>n>>m>>q>>u>>v>>t;
    for(int i=1;i<=n;i++){
        int l; cin>>l;
        q1.push(l);
    }
    for(int i=1;i<=m;i++){
        long long len=max_len(i-1),t1=len*u/v,t2=len-t1;//这里是对蚯蚓进行操作
        q2.push(t1-i*q); q3.push(t2-i*q);
        if(i%t==0)cout<<len<<" ";
    }
    long long len;
    cout<<endl;
    for(int i=1,len=max_len(m);i<=n+m;i++,len=max_len(m)){if(i%t==0) cout<<len<<" ";}
    return 0;
}

现在思考一下,为什么q2,q3可以不用优先队列呢?
因为我们要切的是最长的一只蚯蚓,而切下来的也应该会比之前切下来的长,所以我们只需要保证一开始切下来的是最长的就可以,这样我们接下来找也是最长的(感觉是这个意思)。

posted @ 2020-11-07 21:19  Time_Limit_Exceeded  阅读(108)  评论(0编辑  收藏  举报