P2827 蚯蚓

題目連接

咕咕咕spa

思路

若是是\(q=0\)的話,至關於維護一個集合,支持查詢最大值,刪除最大值,添加新值,用\(set\)便可實現code

若是是\(q>0\)的話,咱們能夠把用刀切當作是,把最大值\(x\),分紅\(\left\lfloor px\right\rfloor-q\)\(x-\left\lfloor px\right\rfloor-q\),而後給把整個集合都加上\(q\),因此咱們能夠維護一個變量\(ans\)表示整個集合的偏移量,集合中的數加上\(ans\)就是真實值開始咱們讓\(ans=0\)排序

對於每一秒:隊列

1.取出集合中的最大值x,令\(x=x+ans\)ci

2.把\(\left\lfloor px\right\rfloor-q\)\(x-\left\lfloor px\right\rfloor-q\)插入集合get

3.令\(ans+=q\)it

用三個隊列\(q1,q2,q3\)共同組成要維護的集合,\(q1\)保存初始的\(n\)個數,從大到小排序。\(q2\)存儲 \(\left\lfloor px\right\rfloor\)class

,\(q3\)存儲 \(x-\left\lfloor px\right\rfloor\) ,每一個時刻最大的數就是\(q1,q2,q3\)隊首之一。變量

咱們來證實一下集合中取出的數是單調遞減的,並且新生成的數也是單調遞減的

由於\(p,q\)是常數,\(0<p<1\)並且\(p\)是非負整數,設\(x_1,x_2\)是非負整數

\(x_1>=x_2\)時,\(\left\lfloor px_1\right\rfloor+q=\left\lfloor px_1+pq\right\rfloor>=\left\lfloor px_2+pq\right\rfloor=\left\lfloor p(x_2+q)\right\rfloor\)

又由於\(x_1>x_2>=p(x_1-x_2)\)

因此\(x_1-px_1>=x_2-px_2>=x_2-p(x_2+q)\)

因此\(x_1-\left\lfloor px_1\right\rfloor+q=\left\lfloor x_1-px_1\right\rfloor+q>=\left\lfloor x_2-p(x_2+q)\right\rfloor+q>=x_2+q-\left\lfloor p(x_2+q)\right\rfloor\)

即:

\(x_1\)\(x_2\)以前被取出集合,那麼一秒以後\(x_1\)被分紅\(\left\lfloor px\right\rfloor-q\)\(x-\left\lfloor px\right\rfloor-q\)分別不小於x_2+q分紅的兩個數

\(\left\lfloor x_2-p(x_2+q)\right\rfloor+q\)\(x_2+q-\left\lfloor p(x_2+q)\right\rfloor\)

證畢(寫死我了)

代碼

#include<bits/stdc++.h>
#include<queue>
#define int long long int
#define p u/v
using namespace std;
int n,m,q,u,v,t,a[7004015];
int cmp(int x,int y) {
    return x>y;
}
queue<int>q1,q2,q3;
int calc(int t) {
    int x=0,a=0,b=0,c=0;
    if(!q1.empty()) a=q1.front()+t*q;
    if(!q2.empty()) b=q2.front()+t*q;
    if(!q3.empty()) c=q3.front()+t*q;
    x=max(a,max(b,c));
    if(x==a) q1.pop();
    else if(x==b) q2.pop();
    else if(x==c) q3.pop();
    return x;
}
signed main() {
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    cin>>n>>m>>q>>u>>v>>t;
    //n只蚯蚓 m秒   p=u/v   t是輸出參數
    for(int i=1; i<=n; ++i) cin>>a[i];
    sort(a+1,a+1+n,cmp);
    for(int i=1; i<=n; ++i) q1.push(a[i]);
    for(int i=1; i<=m; ++i) {
        int x=calc(i-1);
        if(!(i%t)) cout<<x<<' ';
        int now1=x*p;//注意這裏要先乘後除
        int now2=x-now1;
        q2.push(now1-i*q);
        q3.push(now2-i*q);
    }
    cout<<endl;
    for(int i=1; i<=(n+m); ++i) {
        int x=calc(m);
        if(!(i%t)) cout<<x<<' ';
    }
    return 0;
}
相關文章
相關標籤/搜索