zoukankan      html  css  js  c++  java
  • [bzoj1012] [JSOI2008]最大数maxnumber (单调队列)

    单调队列


    Description

      现在请求你维护一个数列,要求提供以下两种操作:
    1、 查询操作。
    语法:Q L
    功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。
    限制:L不超过当前数列的长度。
    2、 插入操作。
    语法:A n
    功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
    模,将所得答案插入到数列的末尾。
    限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
    数。

    Input

      第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
    M行,查询操作或者插入操作。

    Output

      对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。

    Sample Input

    5 100
    A 96
    Q 1
    A 97
    Q 1
    Q 2

    Sample Output

    96
    93
    96


    Solution

    傻逼题,用单调队列搞一搞就可以了。
    维护一个递减的单调队列,二分查找下标。

    Code

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int maxn = 2e5 + 10;
    int m, len, q[maxn], t;
    long long mod, a[maxn], x, las;
    char op[2];
    
    int main() {
    	scanf("%d%lld", &m, &mod);
    	for(int i = 0; i < m; i++) {
    		scanf("%s%lld", op, &x);
    		if(op[0] == 'A') {
    			a[++len] = (x + las) % mod;
    			while(t && a[q[t]] <= a[len]) t--;
    			q[++t] = len;
    		}
    		else {
    			x = len - x;
    			int l = 1, r = t, mid;
    			while(l < r) {
    				mid = (l + r) >> 1;
    				if(q[mid] <= x) l = mid + 1;
    				else r = mid;
    			}
    			las = a[q[l]];
    			printf("%lld
    ", las);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    ABP理论学习之异常处理
    ABP理论学习之导航(Navigation)
    ABP理论学习之验证DTO
    C#程序实现窗体的最大化/最小化
    残缺棋盘的覆盖问题
    23:区间内的真素数
    最大质因子序列
    02:二分法求函数的零点
    01:查找最接近的元素
    最大连续和问题【四种不同的算法】
  • 原文地址:https://www.cnblogs.com/ZegWe/p/6285623.html
Copyright © 2011-2022 走看看