2024年CSP-J暑假冲刺训练营(6):队列/优先队列/前缀和/差分

一、队列

1. 特点

队列是一种数据结构,它按照先进先出(First-In-First-Out,FIFO)的原则存储和访问数据。它类似于现实生活中排队的概念,最先进入队列的元素将最先被访问和删除,而最后进入队列的元素将最后被访问和删除。

2. 数组 / STL

2.1 存储

数组

int q[1010];
int head = 1, tail = 1;

STL

#include <queue>
queue <int> q;

2.2 操作

数组 STL
插入 q[tail++] = x; q.push(x);
删除 head++; q.pop();
判空 head == tail q.empty()
队首 q[head] q.front()
队尾 q[tail] q.back()
大小 tail-head q.size()

3. 优先队列

3.1 存储

#include <queue>
priority_queue <int> q; // 越大优先级越高
priority_queue <int, vector<int>, greater<int> > q; // 越小优先级越高

3.2 操作

操作 程序
插入 q.push(x)
删除 q.pop()
队首 q.top()

二、队列模板

1. 时间最近问题

link #

这是很典型的一道时间最近问题,用一个队列可以保存离当前最近可能满足要求的事物。这个时候,当队头指向的元素超出时间范围,我们就认为其永远无法满足要求,然后踢出队列。

对于求出不同的国籍数量,我们可以用下面几种方法:


  • 程序:a[x]++; if (a[x] == 1) k++;
    特点:支持动态运算
    复杂度: O ( n ) O(n) O(n)
  • 排列
    程序:if (a[i] != a[i-1] k++;
    特点:略
    时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn)
  • 映射
    程序:略
    特点:略
    时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn)

参考程序如下:

#include <iostream>
using namespace std;

struct Node {
   
   
    int x, t;
} q[300500];
int head = 1, tail = 1;

int n, ans;
int t, k, x;
int cnt[100100];

int main() {
   
   
    cin >> n;
    for (int i = 1; i <= n; i++) {
   
   
        cin >> t >> k;
        for (int j = 1; j <= k; j++) {
   
   
            cin >> x;
            cnt[x]++;
            if (cnt[x] == 1) ans++;
            q[tail++] = {
   
   x, t};
        }
        
        while (head < tail) {
   
   
            if (q[head].t + 86400 <= t) {
   
   
                cnt[q[head].x]--;
                if (cnt[q[head].x] == 0) ans--;
                head++;
            } else {
   
   
                break;
            }
        }
        
        cout << ans << endl;
    }
    return 0;
}

2. 队列模拟问题

link #

这就是一道典型的队列模拟题。易错点主要有:

  • tail 指向待放入元素
  • continue 不要写成 break
  • 每轮记得更新 flag = false

参考程序如下:

#include <iostream>
#include <cstdio>
using namespace std;

int cnt;
bool flag;
int m, n, x;
int q[1010];
int head = 1, tail = 1;

int main() {
   
   
    cin >> m >> n;
    for (int i 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值