zoukankan      html  css  js  c++  java
  • 【NOIP2016提高组】蚯蚓

    https://www.luogu.org/problem/show?pid=2827

    首先考虑暴力:
    每次都是拿最长的蚯蚓,容易想到用堆。
    每次除拿出来的以外所有的蚯蚓都增长,容易想到用一个懒惰标记来记录所有的蚯蚓增长了多少。取最大的元素出来后加上标记的值,放元素进去的时候减去标记的值。
    这时已经可以骗到60分了。

    假设某一次取出来的元素长度为x,当前标记的值为inc,切完以后放进去的就是(x+inc)p-(inc+q)、(x+inc)(1-p)-(inc+q)两个元素
    由于
    (x+inc)p-(inc+q)-x=(x+inc)p-(x+inc)-q=(p-1)(x+inc)-q<0
    (x+inc)(1-p)-(inc+q)-x=(x+inc)(1-p)-(x+inc)-q=-p(x+inc)-q<0
    可知放进去的两个元素必定都小于刚取出来的元素,也就是每次放进去的两个元素依次递减。
    因此可以开三个队列,第一个队列存放降序排序后的初始值,剩余两个队列分别存放每次切出来的两个元素。可以保证这三个队列都是单调递减的。每次比较三个队列的头元素,取最大的。
    因为STL自带队列在不开优化的NOIP里比较慢,所以最好手写队列。

    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <functional>
    
    template <class T>
    struct myqueue
    {
    #define maxlength 8000005
        T data[maxlength];
        int p[2] = {0, 0}; // 头尾指针
        int size = 0;
        void push(T val)
        {
            size++;
            data[p[1]] = val;
            if (++p[1] >= maxlength)
                p[1] -= maxlength;
        }
        void pop()
        {
            size--;
            if (++p[0] >= maxlength)
                p[0] -= maxlength;
        }
        T front()
        {
            return data[p[0]];
        }
        bool empty()
        {
            return size == 0;
        }
    };
    
    #define maxn 100005
    using namespace std;
    int n, m, q, t;
    long double p, eps = 1e-6;
    myqueue<int> x, y, z;
    int increase = 0;
    int pop_max()
    {
        int from = 0;
        int ew = -10000000;
        if (!x.empty() && x.front() + increase > ew)
        {
            from = 1;
            ew = x.front() + increase;
        }
        if (!y.empty() && y.front() + increase > ew)
        {
            from = 2;
            ew = y.front() + increase;
        }
        if (!z.empty() && z.front() + increase > ew)
        {
            from = 3;
            ew = z.front() + increase;
        }
        switch (from)
        {
        case 1:
            x.pop();
            break;
        case 2:
            y.pop();
            break;
        case 3:
            z.pop();
            break;
        }
        return ew;
    }
    int tmp[maxn];
    int main()
    {
        ios::sync_with_stdio(false);
        int a, b;
        cin >> n >> m >> q >> a >> b >> t;
        p = a * 1.0 / b;
    
        for (int i = 1; i <= n; i++)
            cin >> tmp[i];
        sort(tmp + 1, tmp + 1 + n, greater<int>());
        for (int i = 1; i <= n; i++)
            x.push(tmp[i]);
    
        int ew;
        for (int i = 1; i <= m; i++)
        {
            ew = pop_max();
            a = ew * p + eps;
            b = ew - a;
            if (i % t == 0)
                cout << ew << ' ';
            increase += q;
            y.push(a - increase);
            z.push(b - increase);
        }
        cout << endl;
        for (int i = 1; i <= m + n; i++)
        {
            ew = pop_max();
            if (i % t == 0)
                cout << ew << ' ';
        }
        cout << endl;
        return 0;
    }
  • 相关阅读:
    TreeView控件应用(包含递归调用)
    FTP操作(FTPClient)
    利用正则表达式 进行字符的判断
    复合查询
    NPOI操作
    导航特效
    拼音检索
    项目中的注意事项
    计算文件的MD5值上传到服务器 下载验证文件是否被篡改
    OLE Automation (C#读取EXCEL)
  • 原文地址:https://www.cnblogs.com/ssttkkl/p/7530546.html
Copyright © 2011-2022 走看看