• CodeForces


    CodeForces - 1237D Balanced Playlist 单调队列

    题意

    (n)首歌循环播放。每首歌都有欢乐值。

    播到某首歌时,如果这首歌的欢乐值小于当前播放过的歌曲的最大值的一半(不四舍五入),则停止。

    对于每首歌,求出这首歌开始能播放多少首歌曲。

    [2leq n leq 10^5 \ 1leq a_i leq 10^9 ]

    如果这首歌会播放无穷次,输出(-1)

    分析

    显然,输出-1的充要条件是当欢乐值最小的歌曲的两倍小于欢乐值最大的歌曲

    剩下的都是可行解。

    很容易想到此题会涉及到连续的区间的最值。有点类似移动窗口问题。

    考虑到如果维护出一个单调递减的队列,如果读入的欢乐值的两倍比队首的欢乐值还小,显然这个时候队首就会在这里结束播放,弹出。

    注意到这个此题就做完了。

    注意的细节

    • 不能真的去算除以2,这样一想还不如用乘去代替
    • 数组要开三倍空间。因为首先是循环播放,其次是会因为有可能要跑一圈才能遍历所有情况。
    • 记录答案数组的时候有可能一些数组不会被更新到,这个时候只需要递推一遍即可。

    代码

    int a[maxn * 3];
    int ans[maxn * 3];
    int main() {
        int mx = -1;
        int mi = INF;
        int n = readint();
        for (int i = 0; i < n; i++)
            a[i] = readint(), mx = max(mx, a[i]), mi = min(mi, a[i]), a[i + n] = a[i + 2 * n] = a[i];
        if (mi * 2 >= mx) {
            for (int i = 0; i < n; i++)
                printf("-1 ");
            return 0;
        }
        deque<int> q;
        for (int i = 0; i < 3 *  n; i++) {
            while (!q.empty() && a[q.back()] < a[i]) q.pop_back();
            q.push_back(i);
            while (a[q.front()] > 2 * a[i]) {
                ans[q.front()] = i - q.front();
                q.pop_front();
            }
        }
        for (int i = 3 * n - 1; i >= 0; i--) 
            if (!ans[i]) ans[i] = ans[i + 1] + 1;
        for (int i = 0; i < n; i++)
            printf("%d ", ans[i]);
    }
    
  • 相关阅读:
    NTP服务器
    sublime中文设置
    13、软件定时器
    晶振和CPU周期
    红外通信协议
    KEIL使用时的一些配置
    STM32 的内部 FLASH
    STM32的程序下载
    2、触摸屏
    目录
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13788397.html
Copyright © 2020-2023  润新知