zoukankan      html  css  js  c++  java
  • 【算法学习笔记】53.单调队列的简单应用 SJTU OJ 1034 二哥的金链

    1034. 二哥的金链

    Description

    一个阳光明媚的周末,二哥出去游山玩水,然而粗心的二哥在路上把钱包弄丢了。傍晚时分二哥来到了一家小旅店,他翻便全身的口袋也没翻着多少钱,而他身上唯一值钱的就是一条漂亮的金链。这条金链散发着奇异的光泽,据说戴上它能保佑考试门门不挂,RP++。好心的老板很同情二哥的遭遇,同意二哥用这条金链来结帐。虽然二哥很舍不得这条金链,但是他必须用它来付一晚上的房钱了。

    金链是环状的,一共有 N 节,老板的要价是 K 节。随便取下其中 K 节自然没问题,然而金链上每一节的 RP 值其实并不一样,有高有低,二哥自己非常清楚。另外二哥并不希望把整个金链都拆散了,他只愿意在这条环形的金链上切两刀,从而切下一段恰好为 K 节的金链给老板。因为 RP 值越高的节越稀有,因此他希望给老板的金链上最高的 RP 值最小。

    Input Format

    第一行两个整数 N 和 K,表示金项链有 N 节,老板要价 K 节。

    第二行用空格隔开的N个正整数 a1...aN ,表示每一节金链的价值为多少。

    Output Format

    输出一个整数,表示二哥给老板的金链上最高的 RP 值最小多少。

    Sample Input

    5 2
    1 2 3 4 5
    

    Sample Output

    2
    

    Sample Input

    6 3
    1 4 7 2 8 3
    

    Sample Output

    4


    最简单就是O(N*K)算法
    有大量重复的比较过程
    想消除重复比较大小的问题要考虑如何利用单调性来完成这件事情,所以就想到了单调队列。

    这里维护一个单调严格递减序列就可以了,记得在考虑出队时,要根据入队的那个元素向前-K个 找到该出队的元素,与队首比较,如果是恰好是,那就出队,否则不用动,因为之前已经维护过了单调性,所以不会有比刚入队小的元素在队首位置。
    因为每一个元素都要经过出队入队的动作 所以是O(N+K-1)
    注意此处把环形过程简化成了数组,用空间换了代码简洁性
    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    int RP[200000+1000];//存储RP
    int front = 0;
    int rear = 0;
    
    bool empty(){
        return front==rear;
    }
    
    void q_out(int x){
        //因为此时x曾经肯定在队列或者已经出队了 如果队首正好是x 那就出队 否则不动
        if(que[front]==x)
            front++;
    }
    
    void q_in(int x){
        //入队时删除所有比它小的元素
        while(!empty()){
            if(que[rear-1]<x)
                rear--;
            else
                break;
        }
        que[rear++] = x;
    }
    
    void print(){
        for (int i = front; i < rear; ++i)
        {
            cout<<que[i]<<" ";
        }
        cout<<endl;
    }
    
    int main(int argc, char const *argv[])
    {
        
        int N,K; //添加环形变化后 长度为N+K-1
        int ans = 0;
        scanf("%d%d",&N,&K);
        for (int i = 1; i <= N; ++i){
            scanf("%d",&RP[i]);
            if(i<=K-1){
                RP[N+i] = RP[i];
            }
        }
        //初始化ans
        for (int i = 1; i <= K; ++i)
        {
            if(ans < RP[i])
                ans = RP[i];
            q_in(RP[i]);
        }
        for (int i = K+1; i <= N+K-1; ++i)
        {
            q_out(RP[i-K]);
            q_in(RP[i]);
            //print();
            if(que[front] < ans)
                ans = que[front];
        }
    
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    HDU 5059 Help him
    HDU 5058 So easy
    HDU 5056 Boring count
    HDU 5055 Bob and math problem
    HDU 5054 Alice and Bob
    HDU 5019 Revenge of GCD
    HDU 5018 Revenge of Fibonacci
    HDU 1556 Color the ball
    CodeForces 702D Road to Post Office
    CodeForces 702C Cellular Network
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/sjtu_oj_1034.html
Copyright © 2011-2022 走看看