队列
Description
你需要维护一个队列,操作共四种,参数分别如下:
- 从队尾依次插入
1,2,3,\cdots,x ; - 弹出队头的前
k 个元素; - 查询队列中的第
k 个元素; - 查询队列中所有元素的最大值。
维护队列的同时对于每个操作三和操作四,输出查询的答案。
Solution
对于操作一,由于
对于操作二和操作三,首先可以想到遍历整个队列,同时维护一个前缀和
由于我们每次都要取一个前缀和,因此我们可以在进行操作一的同时求一下
对于操作四,很显然可以维护一个关于
总时间复杂度为
Code
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 200005;
int q, que[N], front, back, rt, x;
long long id[N], sum[N], p;
int read(){
int x = 0;
char a = getchar();
while(a < '0' || '9' < a) a = getchar();
while('0' <= a && a <= '9') x = (x << 1) + (x << 3) + (a ^ 48), a = getchar();
return x;
}
void write(int x){
if(x > 9) write(x / 10);
putchar(x % 10 | 48);
}
int main(){
q = (read(), read());
for(int i = 1; i <= q; ++ i){
int x = read();
if(x == 1){
x = read();
sum[rt] = sum[rt ++] + x;
while(front <= back && que[back] <= x) back --;
que[++ back] = x;
id[back] = sum[rt];
}
else if(x == 2) p += read();
else if(x == 3){
x = read();
write(p + x - sum[lower_bound(sum + 1, sum + rt, p + x) - sum - 1]), puts("");
}
else if(x == 4){
while(front <= back && id[front] <= p) ++ front;
write(que[front]), puts("");
}
}
return 0;
}
其实也可以再稍微优化掉一个数组