NOIP2016 蚯蚓 队列+单调性优化

版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82250985

传送门

努力刷完NOIP提高组题目ing…
50~60分算法:直接用堆/优先队列模拟
100分算法:观察题目,发现其中隐含的单调性。
设两条蚯蚓长度为 a , b a,b ,其中 a > b a > b
a a 被切掉时长度分别为 p a , ( 1 p ) a pa, (1 - p)a ,过t秒之后长度为 p a t q , ( 1 p ) a + t q pa+tq, (1 - p)a +tq
此时 b b 被取出,长度 b + t q b + tq ,被切之后长度分别为 p ( b + t q ) , ( 1 p ) b + t q p(b + tq),(1 - p)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;
}

猜你喜欢

转载自blog.csdn.net/DyingShu/article/details/82250985