1. 程式人生 > >【NOIP2016提高組day2】蚯蚓

【NOIP2016提高組day2】蚯蚓

AC AS orm max 可能 printf display OS 例如

題目

本題中,我們將用符號 LcJ 表示對 c 向下取整,例如: L3.0J = L3.1J = L3.9J = 3 。 蛐蛐國最近蚯蚓成災了!隔壁跳蚤國的跳蚤也拿蚯蚓們沒辦法,蛐蛐國王只好去 請神刀手來幫他們消滅蚯蚓。
蛐蛐國裏現在共有 n 只蚯蚓( n 為正整數)。 每只蚯蚓擁有長度,我們設第 i 只匠 蚓的長度為 ai ( i = 1, 2, . . . , n ),並保證所有的長度都是非負整數(即:可能存在長度為 0 的蚯蚓)。
每一秒,神刀手會在所有的蚯蚓中,準確地找到最長的那一只(如有多個則任選 一個)將其切成兩半。 神刀手切開蚯蚓的位置由常數 p (是滿足 0 < p < 1 的有理數) 決定,設這只蚯蚓長度為 x ,神刀手會將其切成兩只長度分別為 LpxJ 和 x ? LpxJ 的匠 蚓。特殊地,如果這兩個數的其中一個等於 0 ,則這個長度為 0 的蚯蚓也會被保留。此 外,除了剛剛產生的兩只新蚯蚓,其余蚯蚓的長度都會增加q(是一個非負整常數)。

蛐蛐國王知道這樣不是長久之計,因為蚯蚓不僅會越來越多,還會越來越長。蛐蛐國王決定求助於一位有著洪荒之力的神秘人物,但是救兵還需要 m 秒才能到來. . . . . . ( m 為非負整數)
蛐蛐國王希望知道這 m 秒內的戰況。 具體來說,他希望知道: ? m 秒內,每一秒被切斷的蚯蚓被切斷前的長度(有 m 個數): ? m 秒後,所有蚯蚓的長度(有 n + m 個數)。 蛐蛐國王當然知道怎麽做啦! 但是他想考考你. . . . . .

分析

這題很坑爹,
假設有兩個數x、y,先後被切(x>y),那麽
分別分成xp,x(1-p),yp,y(1-p)。
那麽會先切那條呢?
發現,因為增長的速度一樣,所以就只比較切完y之後。

\(x:xp+q\)
\(y:(y+q)p=yp+qp\)
顯然\[xp+q>yp+qp\]
於是將xp放在yp前面
x(1-p),y(1-p)同理。
那麽我們開三個不上升隊列,
第一個記錄原來的蚯蚓,
第二個記錄乘以p的蚯蚓
第三個記錄乘以(1-p)的蚯蚓,
在記錄每條就要入隊列的時間,就可以求出增加的長度
每次比較三個隊列的隊首,取最大的值x的切。
將xp加入第二個隊列的隊尾
將x(1-p)加入第三個隊列的隊尾
(第二個第三個隊列保證單調,上面證明了)

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=7100005;
using namespace std;
struct ddx
{
    int v,t;
}d[3][N];
int s[3],t[3],n,m,tt,q,v,u;
bool cmp(ddx x,ddx y)
{
    return x.v>y.v;
}
int get(int i,int x)
{
    if(s[i]>t[i]) return -maxlongint;
    return d[i][s[i]].v+q*(x-d[i][s[i]].t-1);
}
int compete(int x)
{
    int pos=0;
    for(int i=0;i<=2;i++)
    {
        if(s[i]<=t[i])
            if(get(i,x)>get(pos,x)) pos=i;
    }
    return pos;
}
int main()
{
    freopen("earthworm.in","r",stdin);
    freopen("earthworm.out","w",stdout);
    scanf("%d%d%d%d%d%d",&n,&m,&q,&u,&v,&tt);
    for(int i=1;i<=n;i++) scanf("%d",&d[0][i].v);
    sort(d[0]+1,d[0]+1+n,cmp);
    s[0]=s[1]=s[2]=1;
    t[0]=n;
    for(int i=1;i<=m;i++)
    {
        int pos=compete(i),val=get(pos,i);
        if(i%tt==0) printf("%d ",val);
        s[pos]++;
        d[1][++t[1]].v=int(u*1.0/v*val);
        d[2][++t[2]].v=val-int(u*1.0/v*val);
        d[1][t[1]].t=i;
        d[2][t[2]].t=i;
    }
    cout<<endl;
    for(int i=1;i<=n+m;i++)
    {
        int pos=compete(m+1),val=get(pos,m+1);
        if(i%tt==0) printf("%d ",val);
        s[pos]++;
    }
}

【NOIP2016提高組day2】蚯蚓