度度熊学队列
度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣。
初始时有 N 个空的双端队列(编号为 1 到 N ),你要支持度度熊的 Q 次操作。
①1 u w val 在编号为 u 的队列里加入一个权值为 val 的元素。(w=0 表示加在最前面,w=1 表示加在最后面)。
②2 u w 询问编号为 u 的队列里的某个元素并删除它。( w=0 表示询问并操作最前面的元素,w=1 表示最后面)
③3 u v w 把编号为 v 的队列“接在”编号为 u 的队列的最后面。w=0 表示顺序接(队列 v 的开头和队列 u 的结尾连在一起,队列v 的结尾作为新队列的结尾), w=1 表示逆序接(先将队列 v 翻转,再顺序接在队列 u 后面)。且该操作完成后,队列 v 被清空。
Input
有多组数据。
对于每一组数据,第一行读入两个数 N 和 Q。
接下来有 Q 行,每行 3~4 个数,意义如上。
N≤150000,Q≤400000
1≤u,v≤N,0≤w≤1,1≤val≤100000
所有数据里 Q 的和不超过500000
Output
对于每组数据的每一个操作②,输出一行表示答案。
注意,如果操作②的队列是空的,就输出−1且不执行删除操作。
Sample Input
2 10
1 1 1 23
1 1 0 233
2 1 1
1 2 1 2333
1 2 1 23333
3 1 2 1
2 2 0
2 1 1
2 1 0
2 1 1
Sample Output
23
-1
2333
233
23333
提示
由于读入过大,C/C++ 选手建议使用读入优化。
一个简单的例子:
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack>
#include<deque>
using namespace std;
deque<int >que[150010];
//#include<bits/stdc++.h>//万能头文件
//deque<int >que[150010];//定义双端队列
int main(){
int n = 0, q = 0;
while(scanf("%d %d",&n,&q)!= EOF){
for(int i = 0; i <= n; i++){
que[i].clear();
}
int a = 0,u = 0,v = 0,w = 0,val = 0;
for(int i = 0; i <q; i++){//进行q此操作
scanf("%d",&a);
if(a == 1){
scanf("%d %d %d",&u,&w,&val);
if(w == 1){
que[u].push_back(val);
}else{
que[u].push_front(val);
}
}else if(a == 2){
scanf("%d %d",&u,&w);
if(!que[u].empty()){
if(w == 1){
// int len = (int)que[u].size();
printf("%d\n",que[u].back());
// printf("%d\n",que[u][len - 1]);
que[u].pop_back();
}else{
printf("%d\n",que[u].front());
// printf("%d\n",que[u][0]);
que[u].pop_front();
}
}else{
printf("-1\n");
}
}else{//a == 3的情况
scanf("%d %d %d",&u,&v,&w);
if(w == 1 && que[v].size() >= 2){
reverse(que[v].begin(),que[v].end());
}
while(!que[v].empty()){//循环的作用是将队列v从前到后全部接在队列v后面
que[u].push_back(que[v].front());//把v队头接到u队尾
que[v].pop_front();//从头开始一个一个删除v队头
}
}
}
}
return 0;
}
看病要排队
看病要排队这个是地球人都知道的常识。
不过经过细心的0068的观察,他发现了医院里排队还是有讲究的。0068所去的医院有三个医生(汗,这么少)同时看病。而看病的人病情有轻重,所以不能根据简单的先来先服务的原则。所以医院对每种病情规定了10种不同的优先级。级别为10的优先权最高,级别为1的优先权最低。医生在看病时,则会在他的队伍里面选择一个优先权最高的人进行诊治。如果遇到两个优先权一样的病人的话,则选择最早来排队的病人。
现在就请你帮助医院模拟这个看病过程。
Input
输入数据包含多组测试,请处理到文件结束。
每组数据第一行有一个正整数N(0<N<2000)表示发生事件的数目。
接下来有N行分别表示发生的事件。
一共有两种事件:
1:"IN A B",表示有一个拥有优先级B的病人要求医生A诊治。(0<A<=3,0<B<=10)
2:"OUT A",表示医生A进行了一次诊治,诊治完毕后,病人出院。(0<A<=3)
Output
对于每个"OUT A"事件,请在一行里面输出被诊治人的编号ID。如果该事件时无病人需要诊治,则输出"EMPTY"。
诊治人的编号ID的定义为:在一组测试中,"IN A B"事件发生第K次时,进来的病人ID即为K。从1开始编号。
Sample Input
7
IN 1 1
IN 1 2
OUT 1
OUT 2
IN 2 1
OUT 2
OUT 1
2
IN 1 1
OUT 1
Sample Output
2
EMPTY
3
1
1
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack>
#include<deque>
using namespace std;
//#include<bits/stdc++.h>//万能头文件
//优先队列priority_queue<node >q[]
/*
struct node{
int x,y,val;
friend bool operator <(node a,node b){//重载 < 运算符(就是它判断小于的条件)
return a.val>b.val;//而这个判断的条件就是 a.val > b.val,该条件满足时,< 重载成功,节点a本身 < 节点b本身
}// 故结构体在优先队列q的排序中b先入队,a再入队,a < b,所以q中的元素就变成按val从小到大排序了
}
运算符重载的示例分析优先队列是从大到小排序的,我们要想变成从小到大排序,需改变一下它判断小于的条件(故重载 < 运算符)
如上面这个例子,
*/
struct node{//病人的信息封装在结构体里
int value,id;//病人的优先级,id
bool operator < (const node &b)const{//运算符重载固定格式(此处重载<),const node &b是用引用传递,比按值传递node b效率更高,效果是一样的
if(value == b.value){
return id > b.id;//定义一种规则,value相等就根据 id判断条件进行重载<,id > b.id成立返回1,则重载<成功;
//即id的前主体反而要 < b.id的主体b本身,故在优先队列中 id小的新传入b 排在 id大的原主体 的前边(插队到入队顺序的前面)
//b在优先队列q[]中从大到小入队,先入的b其id就小,则优先队列q[]按照id则是由小到大排列
}else{
return value < b.value;//定义一种规则,根据value排列,value小的其主体也小;
//因为此时value < b.value,故 前主体 < 传入的新主体b,在优先队列q[]里 新传入的 b本身 就插队到了队前面(插队到入队顺序的前面)
// value值大的b先入队,value值小的b后入队,则优先队列q[]按照value值从大到小排列
}
}
};
int main(){
int t = 0;
while(scanf("%d",&t)!= EOF){
node p;
priority_queue<node >q[4];//定义一个优先队列,容量为10,从0开始到9,为医生数量
int time;
time = 1;
string s;
while(t--){//共t次操作(含IN和OUT)
cin >> s;
if(s == "IN"){
int a;
cin >> a >> p.value;//此处分别输入进入的医生A和的来的病人优先级B.value
p.id = time;//给来的病人编号
time ++;//编号自增
q[a - 1].push(p);//将该组进来的病人B封装进医生(a - 1)的救治名单中,进队,a - 1是从0开始,结构体变量添加到优先队列
}else{//此时为out,输入的医生A要治疗其优先级最高的病人,然后让其出院
int a;
cin >> a;
if(q[a - 1].empty()){//如果给医生未接收到病人
cout << "EMPTY" << endl;
}else{//优先队列.top()表示返回具有最高优先级的元素值,但不删除,而.pop表示删除最高优先级的元素
cout << q[a - 1].top().id << endl;//让该医生优先级最高的病人治疗出院,此处题目要求输出其ID
q[a - 1].pop();//删除医生a - 1的最高优先级的元素(病人)
}
}
}
}
return 0;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。