fzoj 1894 志愿者选拔 (双向队列模板)
2016-05-21 22:28
423 查看
Problem 1894 志愿者选拔
Accept: 1787 Submit: 5571
Time Limit: 1500 mSec Memory Limit : 32768 KB
Problem Description
世博会马上就要开幕了,福州大学组织了一次志愿者选拔活动。参加志愿者选拔的同学们排队接受面试官们的面试。参加面试的同学们按照先来先面试并且先结束的原则接受面试官们的考查。
面试中每个人的人品是主要考查对象之一。(提高人品的方法有扶老奶奶过街,不闯红灯等)
作为主面试官的John想知道当前正在接受面试的同学队伍中人品值最高的是多少。于是他请你帮忙编写一个程序来计算。
Input
输入数据第一行为一整数T,表示有T组输入数据。每组数据第一行为”START”,表示面试开始接下来的数据中有三种情况:
输入 | 含义 | |
1 | C NAME RP_VALUE | 名字为NAME的人品值为RP_VALUE的同学加入面试队伍。(名字长度不大于5,0 <= RP_VALUE <= 1,000,000,000) |
2 | G | 排在面试队伍最前面的同学面试结束离开考场。 |
3 | Q | 主面试官John想知道当前正在接受面试的队伍中人品最高的值是多少。 |
所有参加面试的同学总人数不超过1,000,000
Output
对于每个询问Q,输出当前正在接受面试的队伍中人品最高的值,如果当前没有人正在接受面试则输出-1。
Sample Input
2START
C Tiny 1000000000
C Lina 0
Q
G
Q
END
START
Q
C ccQ 200
C cxw 100
Q
G
Q
C wzc 500
Q
END
Sample Output
10000000000-1
200
100
500
Hint
数据较大建议使用scanf,printf 不推荐使用STL
Source
福州大学第七届程序设计竞赛#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<deque> #define N 1000010 using namespace std; struct zz { int num; int val; }p ; int main() { int t; char s[10]; char name[10]; scanf("%d",&t); while(t--) { int chudui=0; int num=0; scanf("%s",s); deque<zz>q; while(scanf("%s",s)&&strcmp(s,"END")!=0) { if(s[0]=='C') { scanf("%s%d",name,&p[num++].val); p[num-1].num=num-1; while(q.size()>0&&q.back().val<=p[num-1].val) q.pop_back(); q.push_back(p[num-1]); } else if(s[0]=='Q') { while(q.size()>0&&q.front().num<chudui) q.pop_front(); if(q.size()>0) printf("%d\n",q.front().val); else printf("-1\n"); } else if(s[0]=='G') chudui++; } } return 0; }
这是刚开始写的 map+两个队列(当时没看双向队列。。。),果断超时。。。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<map> #include<algorithm> #include<iostream> #define INF 0x3f3f3f3f #define ll long long #define N 1000010 using namespace std; char s[6]; struct zz { char s[8]; int x; friend bool operator < (zz a,zz b) { return a.x<b.x; } }p; struct z { char s[8]; int x; }pp; map<int,int>ss; int main() { int t; scanf("%d",&t); while(t--) { ss.clear(); priority_queue<zz>q; queue<z>qq; while(scanf("%s",s)&&strcmp(s,"END")!=0) { if(strcmp(s,"START")==0) continue; else if(strcmp(s,"C")==0) { scanf("%s%d",pp.s,&pp.x); qq.push(pp); ss[pp.x]++; strcpy(p.s,pp.s); p.x=pp.x; q.push(p); } else if(strcmp(s,"G")==0) { pp=qq.front(); qq.pop(); ss[pp.x]--; } else if(strcmp(s,"Q")==0) { if(qq.empty()) printf("-1\n"); else { p=q.top(); while(!ss[p.x]) { q.pop(); p=q.top(); } printf("%d\n",p.x); } } } } return 0; }
介绍一下双向队列的知识:
C++ Deque(双向队列)
是一种优化了的、对序列两端元素进行添加和删除操作的基本序列容器。它允许较为快速地随机访问,但它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个映射结构中保存对这些块及其顺序的跟踪。向deque 两端添加或删除元素的开销很小。它不需要重新分配空间,所以向末端增加元素比vector 更有效。
实际上,deque 是对vector 和list 优缺点的结合,它是处于两者之间的一种容器。
Deque 的特点:
(1) 随机访问方便,即支持[
] 操作符和vector.at() ,但性能没有vector 好;
(2) 可以在内部进行插入和删除操作,但性能不及list ;
(3) 可以在两端进行push 、pop ;
(4) 相对于verctor 占用更多的内存。
双向队列和向量很相似,但是它允许在容器头部快速插入和删除(就像在尾部一样)。
1.Constructors 创建一个新双向队列
语法:
deque();//创建一个空双向队列
deque( size_type size );// 创建一个大小为size的双向队列
deque( size_type num, const TYPE &val ); //放置num个val的拷贝到队列中
deque( const deque &from );// 从from创建一个内容一样的双向队列
deque( input_iterator start, input_iterator end );
// start 和 end
- 创建一个队列,保存从start到end的元素。
2.Operators 比较和赋值双向队列
//可以使用[]操作符访问双向队列中单个的元素
3.assign() 设置双向队列的值
语法:
void assign( input_iterator start, input_iterator end);
//start和end指示的范围为双向队列赋值
void assign( Size num, const TYPE &val );//设置成num个val。
4.at() 返回指定的元素
语法:
reference at( size_type pos ); 返回一个引用,指向双向队列中位置pos上的元素
5.back() 返回最后一个元素
语法:
reference back();//返回一个引用,指向双向队列中最后一个元素
6.begin() 返回指向第一个元素的迭代器
语法:
iterator begin();//返回一个迭代器,指向双向队列的第一个元素
7.clear() 删除所有元素
8.empty() 返回真如果双向队列为空
9.end() 返回指向尾部的迭代器
10.erase() 删除一个元素
语法:
iterator erase( iterator pos ); //删除pos位置上的元素
iterator erase( iterator start, iterator end ); //删除start和end之间的所有元素
//返回指向被删除元素的后一个元素
11.front() 返回第一个元素的引用
12.get_allocator() 返回双向队列的配置器
13.insert() 插入一个元素到双向队列中
语法:
iterator insert( iterator pos, size_type num, const TYPE &val ); //pos前插入num个val值
void insert( iterator pos, input_iterator start, input_iterator end );
//插入从start到end范围内的元素到pos前面
14.max_size() 返回双向队列能容纳的最大元素个数
15.pop_back() 删除尾部的元素
16.pop_front() 删除头部的元素
17.push_back() 在尾部加入一个元素
18.push_front() 在头部加入一个元素
19.rbegin() 返回指向尾部的逆向迭代器
20.rend() 返回指向头部的逆向迭代器
21.resize() 改变双向队列的大小
22.size() 返回双向队列中元素的个数
23.swap() 和另一个双向队列交换元素
语法:
void swap( deque &target );// 交换target和现双向队列中元素
相关文章推荐
- myelipse在本地使用SVN
- Deploy Helion Openstack 2.0 KVM for Ceph
- C++的初始化列表(Initilization List)
- python 进阶学习:列表解析效率和timeit模块
- polymorphism(多态整理)
- 人月神话阅读笔记01
- hdu 1010 Tempter of the Bone
- 程序员,要不要考软考高级职称?
- 向主考官提出的10个漂亮的问题
- 编码规范-如何写个优美的函数
- 一个人的旅行
- STL的仿函数 和函数指针传参
- iOS学习之UIView
- 第十二周工作总结
- 学习进度条12
- 【转载】Qt Quick 之 QML 与 C++ 混合编程详解
- web前端性能优化总结
- Codeforces Round #353 (Div. 2) A B C D map迭代器
- c++作业6
- 图片反转