NOIP2016 蚯蚓 队列+单调性优化

传送门

努力刷完NOIP提高组题目ing…
50~60分算法:直接用堆/优先队列模拟
100分算法:观察题目,发现其中隐含的单调性。
设两条蚯蚓长度为 a , b a,b a,b,其中 a > b a > b a>b
a a a被切掉时长度分别为 p a , ( 1 − p ) a pa, (1 - p)a pa,(1p)a,过t秒之后长度为 p a + t q , ( 1 − p ) a + t q pa+tq, (1 - p)a +tq patq,(1p)a+tq
此时 b b b被取出,长度 b + t q b + tq b+tq,被切之后长度分别为 p ( b + t q ) , ( 1 − p ) b + t q p(b + tq),(1 - p)b + tq p(b+tq),(1p)b+tq
显然a的两段长度还是大于b的两段。
由此,我们可以建立3个队列,分别是没切过的蚯蚓切过之后较长的一段蚯蚓切过之后较短的一段蚯蚓

  • 每次比较三个队列的队头(因为满足单调性),取出最长的一段切掉,把长的一段和短的一段分别加到两个队列中。

注意细节。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;


int q[3][20000001], l[3], r[3];

inline int read(){
    int k = 0; char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9') k = (k<<3) + (k<<1) + ch - 48, ch = getchar();
    return k;
}

inline bool cmp(int a, int b){
    return a > b;
}

inline int Find_Max(){
    int Max = -0x7fffffff, opt = 0;
    for(int i = 0; i < 3; i++)
        if(l[i] <= r[i] && q[i][l[i]] > Max)
            Max = q[i][l[i]], opt = i;
    return opt;
}

int main(){
    int n = read(), m = read(), R = read();
    int U = read(), V = read(), t = read();
    for(int i = 1; i <= n; i++){
        q[0][i] = read();
    }
    sort(q[0] + 1, q[0] + n + 1, cmp); l[0] = 1, r[0] = n;
    l[1] = l[2] = 1, r[1] = r[2] = 0;
    int tag = 0;
    for(int i = 1; i <= m; i++){
        int opt = Find_Max();
        int u = q[opt][l[opt]++] + tag; tag += R;
        int Worm1 = (int)((long long)u * U / V), Worm2 = u - Worm1;
        if(Worm2 > Worm1) swap(Worm2, Worm1);
        q[1][++r[1]] = Worm1 - tag, q[2][++r[2]] = Worm2 - tag;
        if(i % t == 0) printf("%d ", u);
    }
    printf("\n");
    for(int i = 1; i <= n + m; i++){
        int opt = Find_Max();
        if(i % t == 0) printf("%d ", q[opt][l[opt]] + tag);
        l[opt]++;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值