【NOIP2016 D2 T2】蚯蚓

网上都有,自己搜去

暴力

65分暴力:用个优先队列,然后模拟,复杂度 O(m log (n+m)) O ( m   l o g   ( n + m ) )
代码见下:

#include 
using namespace std;

#define R register

int n,m,q,t,nowtime;
double u,v,p;
struct QY
{
    int len,born;
    QY() {len=0,born=0;}
    int glen() {return len+(nowtime-born)*q;}
    friend bool operator < (const QY &x,const QY &y)
    {
        return x.len+(nowtime-x.born)*q < y.len+(nowtime-y.born)*q;
    }
};
priority_queue vector,less > Q;

int main()
{
    scanf("%d %d %d %lf %lf %d",&n,&m,&q,&u,&v,&t);
    p = u/v;
    for (R int i=1;i<=n;++i)
    {
        R int tmp;
        R QY tmp1;
        scanf("%d",&tmp);
        tmp1.len=tmp,tmp1.born=0;
        Q.push(tmp1);
    }
    for (nowtime=0; nowtimeif(!((nowtime+1)%t)) printf("%d ",tmp1.glen());
        Q.pop();
        R int len1=floor((double)tmp1.glen()*p),len2=tmp1.glen()-len1;
        ++ nowtime;
        R QY tmp2,tmp3;
        tmp2.len=len1,tmp3.len=len2,tmp2.born=tmp3.born=nowtime;
        Q.push(tmp2); Q.push(tmp3);
    }
    puts("");
    R int cnt=0;
    while(!Q.empty())
    {
        ++ cnt;
        R QY tmp1=Q.top();
        if(!(cnt%t)) printf("%d ",tmp1.glen());
        Q.pop();
    }
    return 0;
}

正解

这数据明显卡 log 。。。太恶劣了
初始蚯蚓们构成一个序列,
我们可以发现增长长度 q q 是个常数,也就是初始蚯蚓们是同步增长的,
所以对初始序列sort后,它就是个单调不严格递减的队列,这个队列最长的蚯蚓就是队首
于是我们把被砍成一份的塞到一个队列里,另一份塞到另一个队列里。
我们可以证明这两个队列也是单调不严格递减的。
证明:
由于两个队列具对称性,我们证明其中一个就好了。
设有两个先后被砍的蚯蚓为 x,y x , y ,其中 x x 先于 y y 被砍。
设中间过程过了 t t 的时间。
那么放入这个队列里的蚯蚓按先后顺序长度分别为 lenxp+tq,(leny+tq)p l e n x p + t q , ( l e n y + t q ) p (有没有下取整影响不大)
很明显,由于 p1 p ≤ 1 lenxp+tqlenyp+tqp l e n x p + t q ≤ l e n y p + t q p ,因此按照砍的先后顺序塞入队列中,这两个队列同样保持单调。
这样我们每次从三个队列中取个最大的抓出来砍掉,再塞入后两个队列,复杂度就变成线性的了。
代码如下,闲的无聊手写了个小队列模板:

#include 
using namespace std;

#define R register
#define Maxn 100005
#define Maxm 7000005

int n,m,q,t;
struct QY 
{
    int len,born;
    QY(){len=0;born=0;}
    inline int getlen(R int tim){return len+(tim-born)*q;}
};
inline bool cmp(R QY xx,R QY yy) {return xx.len>yy.len;}
struct Que
{
    QY q[Maxm];
    int head,tail;
    Que(){memset(q,0,sizeof q);head=1,tail=0;}
    inline QY front() {return q[head];}
    inline void pop() {++head;}
    inline void push(R QY val) {q[++tail]=val;}
    inline bool empty() {return head > tail;}  
}s[3];
double u,v,p; 
int dmax(R int tim)
{
    R int maxx=-1,maxi=-1;
    for(R int i=0;i<3;++i) 
    {
        if(s[i].empty()) continue;
        R int tmp=s[i].front().getlen(tim);
        if(tmp > maxx) maxx=tmp,maxi=i;
    }
    return maxi;
}
int main()
{
    scanf("%d %d %d %lf %lf %d",&n,&m,&q,&u,&v,&t);
    p = u/v;
    for (R int i=1;i<=n;++i) 
    {
        R QY tmp; 
        scanf("%d",&tmp.len);
        s[0].push(tmp);
    }
    sort(s[0].q+1,s[0].q+n+1,cmp);
    for (R int i=1;i<=m;++i)
    {
        R int Maxq=dmax(i-1),tmp=s[Maxq].front().getlen(i-1);
        if(!(i%t)) printf("%d ",tmp);
        s[Maxq].pop();
        R int len1=floor(double(tmp*p)),len2=tmp-len1;
        R QY tmp1;
        tmp1.len=len1;tmp1.born=i;s[1].push(tmp1);
        tmp1.len=len2;s[2].push(tmp1);
    }
    puts("");
    for(R int i=1;i<=n+m;++i)
    {
        R int Maxq=dmax(m),tmp=s[Maxq].front().getlen(m);
        if(!(i%t)) printf("%d ",tmp);
        s[Maxq].pop(); 
    }
    return 0;
}

你可能感兴趣的:(数据结构)