码迷,mamicode.com
首页 > Web开发 > 详细

BZOJ 1012 [JSOI2008]最大数maxnumber

时间:2016-01-04 22:29:53      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:

怎么做都可以题。。可以用线段树。。可以用平衡树。。反正有不少方法

个人比较滋磁单调队列+二分查找的写法,常数小代码少易理解。

具体思路就是维护一个单调不上升的单调队列,然后查询就在这个单调队列中二分查找就好啦~

 

技术分享
//这道题,可以算是单调队列的一个妙用了
//当然,做法有很多,可以用线段树、平衡树、树状数组等,其中单调队列最巧妙且最简单

//为什么这道题可以使用单调队列呢?
//(即队列中存储的序列必定是下标单调并且数值单调) 
//如果每个结点没有下标优势(早点入队)也没有数值优势(更大),那么显然无论如何都不能作为答案
//然后如何查询呢?
//显然,使用顺序查找必定是会超时的
//注意到下标单调,满足可以使用二分答案的条件。我们可以使用二分答案来找到查询的位置
//(在满足 该节点的下标>=查询的最左边的下标 的前提下下标最小的元素) 

#include <deque>
#include <cstdio>

using namespace std;

struct node
{
    node(const size_t &a = 0, const int &b = 0) : Number(a), Value(b) {}
    size_t Number;
    int Value;
};

unsigned int M;
int D;

size_t Len;
deque<node> S;

int t;

int Search(const size_t &Left)
{
    size_t l(0), r(S.size()), mid;
    
    while (l < r)
    {
        mid = l + ((r - l) >> 1);
        if (S[mid].Number >= Left)
            r = mid;
        else
            l = mid + 1;
    }
    
    return S[l].Value;
}

int main()
{
    char op[10];
    int Input;
    
    scanf("%u%d", &M, &D);
    while (M--)
    {
        scanf("%s%d", op, &Input);
        
        if (*op == A)
        {
            Input += t;
            Input %= D;
            while (S.empty() == false && S.back().Value < Input)
                S.pop_back();
            S.push_back(node(++Len, Input));
        }
        else
            printf("%d\n", t = (S.empty() ? 0 : Search(Len - Input + 1)));
    }
    
    return 0;
}
BZOJ 1012

 

BZOJ 1012 [JSOI2008]最大数maxnumber

标签:

原文地址:http://www.cnblogs.com/Created-equal/p/5100418.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!