在C++ STL中,queuedeque的入队和出队操作有明确的规范,但它们的行为有所不同。以下是详细说明:

1. std::queue(队列,FIFO)

  • 入队(push):加到队尾
    queue<int> q;
    q.push(1);  // 队尾:[1]
    q.push(2);  // 队尾:[1,2]
    
  • 出队(pop):从队首移除
    q.pop();    // 移除1,剩下:[2]
    
  • 访问
    • q.front():队首元素
    • q.back():队尾元素

2. std::deque(双端队列)

支持两端操作:

  • 队尾操作
    deque<int> dq;
    dq.push_back(1);  // 队尾:[1]
    dq.push_back(2);  // 队尾:[1,2]
    dq.pop_back();    // 移除2,剩下:[1]
    
  • 队首操作
    dq.push_front(0); // 队首:[0,1]
    dq.pop_front();   // 移除0,剩下:[1]
    
  • 随机访问
    dq[0];  // 访问第0个元素
    

关键区别

操作 queue deque
入队 push(队尾) push_back/push_front
出队 pop(队首) pop_back/pop_front
访问队首 front() front()
访问队尾 back() back()
随机访问 不支持 支持(如dq[2]

为什么滑动窗口用deque

在滑动窗口最小值的算法中,我们需要:

  1. 从队尾移除比当前元素大的值(保持单调性)
  2. 从队首移除过期元素(超出窗口范围)
  3. 从队尾添加新元素

这正是deque支持的高效操作:

deque<int> dq;
// 维护单调递增队列
for (int i = 0; i < n; ++i) {
    // 1. 移除队尾比当前元素大的
    while (!dq.empty() && nums[dq.back()] >= nums[i]) {
        dq.pop_back();
    }
    // 2. 添加当前索引
    dq.push_back(i);
    // 3. 移除过期队首
    while (dq.front() <= i - k) {
        dq.pop_front();
    }
    // 当前窗口最小值是nums[dq.front()]
}

总结

  • queue:严格的FIFO,只能操作队首和队尾

  • deque:灵活的双端操作,适合需要两端修改的场景(如滑动窗口)

    include

    include

    include

    using namespace std;

    int main() {
    vector cars;
    vector requires;
    int num;

    // 读取cars数组
    while (cin >> num) {
    cars.push_back(num);
    if (cin.get() == '\n') break;
    }

    // 读取requires数组
    while (cin >> num) {
    requires.push_back(num);
    if (cin.get() == '\n') break;
    }

    deque q(requires.begin(), requires.end());
    int K = 0;
    int allocations = 0;
    int remaining = q.size();

    for (int car : cars) {
    K += car;

    while (!q.empty()) {
    int max_len = 0;
    int current_sum = 0;
    int left = 0;
    int best_left = -1;
    int best_right = -1;

    // 滑动窗口找最长子序列
    for (int right = 0; right < q.size(); ++right) {
    current_sum += q[right];
    while (current_sum > K && left <= right) {
    current_sum -= q[left];
    left++;
    }
    if (right - left + 1 > max_len) {
    max_len = right - left + 1;
    best_left = left;
    best_right = right;
    }
    }

    if (max_len == 0) {
    break; // 无法分配,退出循环
    }

    // 执行分配
    allocations++;
    remaining -= max_len;

    // 移除已分配的元素
    deque new_q;
    for (int i = 0; i < q.size(); ++i) {
    if (i < best_left || i > best_right) {
    new_q.push_back(q[i]);
    }
    }
    q = new_q;

    // 重置K,因为已分配
    K = 0;
    if (q.empty()) break; // 需求队列为空,无需继续
    }
    }

    cout << allocations << " " << remaining << endl;
    return 0;
    }