洛谷P2827 蚯蚓 队列 + 观察

时间:2022-11-24 22:11:57

我们不难发现先被切开的两半一定比后被切开的两半大,这样就天然的生成了队列的单调性,就可以省去一个log。所以,我们开三个队列,分别为origin,big,small,每次查询时将三个队列的对头进行比较即可。
Code:

#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 500000 + 4;
bool cmp(int i,int j){return i > j;}
struct Node{
    int length;
    int  pre;
    Node(int length = 0, int pre = 0):length(length), pre(pre){}
};
queue<Node> small, big;
queue<int>origin;
priority_queue<int> fin;
int val[maxn];
int main()
{
   // freopen("in.txt","r",stdin);
    int n,m,p,u,v,t;
    scanf("%d%d%d%d%d%d",&n,&m,&p,&u,&v,&t);
    double perc = (double ) u / v;
    for(int i = 1;i <= n; ++i)scanf("%d",&val[i]);
    sort(val + 1,val + 1 + n, cmp);
    for(int i = 1;i <= n; ++i)origin.push(val[i]);
    for(int i = 1;i <= m; ++i)
    {
        int  a = 0, b = 0, c = 0, ans;
        if(!origin.empty()) a = origin.front() + p * (i - 1);
        if(!small.empty())  b = small.front().length + (i - small.front().pre) * p;
        if(!big.empty())    c = big.front().length + (i - big.front().pre) * p;
        ans = max(a, max(b, c));
        if(i % t == 0) printf("%d ",ans); 
        if(ans == a) origin.pop();
        else if(ans == b) small.pop();
        else big.pop();
        int sm = floor((double)ans * perc) ;
        int bm = ans - sm;
        if(bm < sm) swap(bm,sm);
        small.push(Node(sm,i + 1));
        big.push(Node(bm,i + 1));
    }
    printf("\n");
    while(!origin.empty()){ fin.push(origin.front() + p * (m)); origin.pop(); }
    while(!small.empty()){ fin.push(small.front().length + p * (m - small.front().pre + 1)); small.pop();}
    while(!big.empty()){ fin.push(big.front().length + p * (m - big.front().pre + 1)) ; big.pop();}
    int cnt = 0;
    while(!fin.empty())
    {
        ++cnt;
        if(cnt % t == 0) printf("%d ",fin.top());
        fin.pop();
    }
    return 0;
}