一道比较有意思的题目,我把队列改造了一下然后ac了,后来学数据结构的时候发现我改的队列还有个名词,叫单调队列,心里颇为激动,于是把题目和我的代码发上来与大家分享一下。

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

说明

对40%的数据,3≤N≤200 ;

对70%的数据,3≤N≤20000;

对100%的数据,3≤N≤200000 , 0<ai≤109。

数据规模较大,建议用scanf("%d", &a[i]);来读数据。

说的简单点,就是n个数组成一个圆环,每相邻的k个数中会有一个最大值,一共有n组最大值,然后找出n个最大值中的最小的那个。

直接暴力算的话,对于每个k个数的组,扫一遍可找到最大值,n组每组扫一遍,时间复杂度O(k*n)。这显然不是最理想的,因为相邻的两个组之间,共有的数被重复检查。

考虑维护一个队列,队列中有k个元素,一开始可初始化为圆环的前k个元素,此时,可以扫一遍找出当前队列中的最大值,然后不断地将队首元素出队,队尾则将圆环上新的数入队,然后维护队列的最大值,每次更新队列之后将新的最大值与已经获得的最大值比较并取小的即可。

然后发现一个事实:由于我们关心的是队列的最大值,所以当队列中进入一个较大的元素时,可以舍弃掉原队列中的较小元素。假设队列中原有元素为a1,a2,...,am, 新入队元素为b,则可以从队尾向前搜索,将所有比b小的元素出队,然后将b入队。这样维护的话,整个队列将是单调递减的,所以每次询问最大值的时候直接返回队首元素即可!

另外这样做的话,队列不能记忆那些较小的元素,所以在出队的时候需要知道让哪个数出队,假设我们要让b出队,则队首元素要么比b大,要么等于b!(因为b曾经在队列中,所以比b小的已经在b入队时被挤出队了)若队首元素大于b,则不操作,若队首元素等于b,则队首出队即可。

表面上看,每次入队的时候似乎要从后往前扫一遍队列,即入队时间复杂度O(n),其实不然,若某次入队将较多的元素挤出队,则队列的规模将减小。实际上,对于每个元素,无非就是1次入队,1次出队(被挤出队或是正常出队),从均摊的角度看,入队时间为O(1)!另显然出队操作和询问队列最大值也是O(1),在建队时有k次入队,此后有n次询问、出队和入队,总时间复杂度为O(n+k),这是比较理想的。

以下是我的代码,欢迎高手来拍砖指点。

 1 #include <iostream>
 2 #include <cstdio>
 3
 4 using namespace std;
 5
 6 class monotoneQue
 7 {
 8     int *data;
 9     int front;
10     int rear;
11     int maxsize;
12 public:
13     monotoneQue(int initsize=10):front(0),rear(0),maxsize(initsize)
14     {
15         data=new int[maxsize];
16     }
17     ~monotoneQue(){delete [] data;}
18     void enqueue(int x)
19     {
20         while(rear!=front&&data[(rear-1)%maxsize]<x)
21         {
22             rear=(rear-1)%maxsize;
23         }
24         data[rear]=x;
25         rear=(rear+1)%maxsize;
26     }
27     void dequeue(int x)
28     {
29         if(data[front]==x)
30         {
31             front=(front+1)%maxsize;
32         }
33     }
34     bool isempty(){return front==rear;}
35     int head(){return data[front];}
36 };
37
38 monotoneQue que(200000);
39
40 int main()
41 {
42     int n,k;
43     cin>>n>>k;
44     int rp[n];
45     for(int i=0;i<n;++i)
46     {
47         scanf("%d",&rp[i]);
48     }
49
50     int min_temp;
51     for(int i=0;i<k;++i)
52     {
53         que.enqueue(rp[i]);
54     }
55     min_temp=que.head();
56     if(n==k)
57     {
58         cout<<min_temp<<endl;
59         return 0;
60     }
61     int p=k;
62     while(p!=k-1)
63     {
64         que.dequeue((p-k<0)?(rp[p-k+n]):(rp[p-k]));
65         que.enqueue(rp[p]);
66         if(min_temp>que.head())
67         {
68             min_temp=que.head();
69         }
70         //cout<<min_temp<<" "<<que.head()<<" "<<p<<endl;
71         p=((p+1==n)?(0):(p+1));
72     }
73
74     cout<<min_temp<<endl;
75
76     return 0;
77 }

转载于:https://www.cnblogs.com/xiaodd/p/4266547.html

sjtu oj 1034 二哥的金链相关推荐

  1. 1034. 二哥的金链

    Description 一个阳光明媚的周末,二哥出去游山玩水,然而粗心的二哥在路上把钱包弄丢了.傍晚时分二哥来到了一家小旅店,他翻便全身的口袋也没翻着多少钱,而他身上唯一值钱的就是一条漂亮的金链.这条 ...

  2. 【算法学习笔记】65. 双向扫描 SJTU OJ 1382 畅畅的牙签盒

    http://acm.sjtu.edu.cn/OnlineJudge/problem/1382 注意到 排序之后 i从前向后扫描时,cur恰好是从后向前的,所以即使是双重循环,也是O(n)的算法. # ...

  3. neuq oj 1034: C基础-求同存异 C++

    1034: C基础-求同存异 时间限制: 1 Sec   内存限制: 128 MB 提交: 173   解决: 96 [ 提交][ 状态][ 讨论版] 题目描述 输入两个数组(数组元素个数6和8),输 ...

  4. 一本通OJ 1034:计算三角形面积

    1034:计算三角形面积 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 39036     通过数: 11764 [题目描述] 平面上有一个三角形,它的三个顶点坐 ...

  5. 【算法学习笔记】43.动态规划 逆向思维 SJTU OJ 1012 增长率问题

    1012. 增长率问题 Description 有一个数列,它是由自然数组成的,并且严格单调上升.最小的数不小于S,最大的不超过T.现在知道这个数列有一个性质:后一个数相对于前一个数的增长率总是百分比 ...

  6. 【算法学习笔记】57. 前缀树 字典序优化技巧 STL学习 SJTU OJ 1366 前缀匹配

    Description 给出一个总字符个数大小不超过1,000,000的字典(这个字典的单词顺序不为字典序)和不超过1000个长度不超过1000的前缀,输出字典中匹配该前缀,字典序为K_i的单词在字典 ...

  7. 【算法学习笔记】35.高精度 竖式乘法 SJTU OJ 1274

    Description 输入a,b 输出a*b的竖式乘法,格式见样例. Sample Input1 11 9 Sample Output1 119 -- 99 Sample Input2 10 10 ...

  8. 【算法学习笔记】83.排序辅助 动态规划 SJTU OJ 1282 修路

    此题倒是能用贪心骗点分... 其实对于每一个位置 , 我们知道最后的改善结果一定是原数列中的数 . (因为要尽量减少消耗, 可以考虑减小至和相邻的相同) 有了这个结论之后, 我们就考虑用dp来做这件事 ...

  9. SJTU OJ 3046 足球 题解

    2019独角兽企业重金招聘Python工程师标准>>> 3046. 足球 Description 众所周知,一只足球队由11球员组成,其中有一名守门员和一名队长. 现在,有22人组成 ...

最新文章

  1. 数学各个研究方向简介
  2. 2018人工智能期末考试复习资料(一):学术篇
  3. Vue.extend
  4. mysql查看是否开启定时器_Mysql 查看定时器 打开定时器 设置定时器时间
  5. javaScript 中 call 函数的用法说明
  6. 27_线程安全操作及其案例
  7. python 方差_python统计分析总体方差检验
  8. Delphi中怎么结束线程(这个线程是定时执行的)(方案一)
  9. [tips]ubuntu 12.04系统黑屏
  10. [OpenGL] OpenGL制作三维字符雨屏保程序
  11. 统一管理所有随机启动的应用程序
  12. java JDBC编程
  13. 全文搜索功能--solr
  14. 双币对冲外汇ea ,单货币对冲策略, EA运行原理
  15. 小勇机器人如何绑定_‎App Store 上的“小勇机器人”
  16. VS Code实现python代码语法检查、格式规范化、自动换行字数限制
  17. 语音芯片选型基础,如何计算声音文件的大小?
  18. clickhouse 在货拉拉的应用实践,千亿级别数据实现秒级查询
  19. 微信公众号网页授权--前端获取code及用户信息(vue)【简单详细版】
  20. [附源码]Python计算机毕业设计SSM京津冀畅游网设计(程序+LW)

热门文章

  1. apache kafka系列之broker内部架构
  2. matlab函数 randperm()的用法
  3. 重装完centos6.5后没有网卡驱动的解决方法
  4. 阅读《构建之法》并提问
  5. 啊哈添柴挑战Java1012. 打印字符
  6. 参数在c语言中,C语言函数调用和参数传递
  7. Android底层驱动开发 -驱动配置篇
  8. 深度学习模型压缩算法综述(二):模型剪枝算法
  9. Matlab中类构造函数方法
  10. SAMSUNG U608