#P3486. 第1题-冬季暖系统温度稳定性分析
-
1000ms
Tried: 1344
Accepted: 286
Difficulty: 5
所属公司 :
华为
时间 :2025年8月27日-国内-非AI方向(通软&嵌软&测试&算法&数据科学)
-
算法标签>双指针
第1题-冬季暖系统温度稳定性分析
思路
-
双指针滑动窗口 + 单调队列维护区间最小值与最大值
- 设左右指针 l,r 表示当前窗口。
- 两个单调队列分别维护区间内的最小值与最大值(存下标),支持 O(1) 获取当前 min 与 max。
- 若遇到温度不在 [18,24],将窗口与队列清空,并令 l=r+1。
- 每次加入新元素后,若 max−min>4,从左收缩窗口,同时维护队列头。
- 用 bestLen 记录当前最长长度,长度相等则一并记录。
复杂度
- 时间复杂度:O(N)
- 空间复杂度:O(N)(队列与结果存储)
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
if (!(cin >> N)) return 0;
vector<int> a;
a.reserve(N);
int x;
while ((int)a.size() < N && (cin >> x)) a.push_back(x);
N = (int)a.size();
deque<int> minq, maxq; // 存下标,minq 单调递增(值),maxq 单调递减(值)
int l = 0;
int bestLen = 0;
vector<pair<int,int>> ans;
for (int r = 0; r < N; ++r) {
int v = a[r];
// 若不在 [18,24],窗口重置
if (v < 18 || v > 24) {
minq.clear();
maxq.clear();
l = r + 1;
continue;
}
// 维护单调队列(插入 r)
while (!minq.empty() && a[minq.back()] >= v) minq.pop_back();
minq.push_back(r);
while (!maxq.empty() && a[maxq.back()] <= v) maxq.pop_back();
maxq.push_back(r);
// 收缩直到满足 max - min <= 4
while (!minq.empty() && !maxq.empty() && a[maxq.front()] - a[minq.front()] > 4) {
if (minq.front() == l) minq.pop_front();
if (maxq.front() == l) maxq.pop_front();
++l;
}
// 记录答案
int len = r - l + 1;
if (len > 0) {
if (len > bestLen) {
bestLen = len;
ans.clear();
ans.emplace_back(l, r);
} else if (len == bestLen) {
ans.emplace_back(l, r);
}
}
}
for (auto &p : ans) {
cout << p.first << ' ' << p.second << '\n';
}
return 0;
}
Python
import sys
from collections import deque
def main():
data = list(map(int, sys.stdin.read().strip().split()))
if not data:
return
N = data[0]
arr = data[1:1+N]
N = len(arr)
minq = deque() # 存下标,值单调递增
maxq = deque() # 存下标,值单调递减
l = 0
bestLen = 0
ans = []
for r in range(N):
v = arr[r]
# 不在 [18,24],重置窗口
if v < 18 or v > 24:
minq.clear()
maxq.clear()
l = r + 1
continue
# 插入 r,维护单调性
while minq and arr[minq[-1]] >= v:
minq.pop()
minq.append(r)
while maxq and arr[maxq[-1]] <= v:
maxq.pop()
maxq.append(r)
# 收缩直到满足 max - min <= 4
while minq and maxq and (arr[maxq[0]] - arr[minq[0]] > 4):
if minq[0] == l:
minq.popleft()
if maxq[0] == l:
maxq.popleft()
l += 1
length = r - l + 1
if length > 0:
if length > bestLen:
bestLen = length
ans = [(l, r)]
elif length == bestLen:
ans.append((l, r))
out = sys.stdout
for s, e in ans:
out.write(f"{s} {e}\n")
if __name__ == "__main__":
main()
Java
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
FastScanner fs = new FastScanner(System.in);
Integer nObj = fs.nextInt();
if (nObj == null) return;
int N = nObj;
List<Integer> arrList = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
Integer val = fs.nextInt();
if (val == null) break;
arrList.add(val);
}
int Nreal = arrList.size();
int[] a = new int[Nreal];
for (int i = 0; i < Nreal; i++) a[i] = arrList.get(i);
Deque<Integer> minq = new ArrayDeque<>(); // 存下标,值单调递增
Deque<Integer> maxq = new ArrayDeque<>(); // 存下标,值单调递减
int l = 0, bestLen = 0;
List<int[]> ans = new ArrayList<>();
for (int r = 0; r < Nreal; r++) {
int v = a[r];
// 不在 [18,24],重置窗口
if (v < 18 || v > 24) {
minq.clear();
maxq.clear();
l = r + 1;
continue;
}
// 插入 r,维护单调性
while (!minq.isEmpty() && a[minq.peekLast()] >= v) minq.pollLast();
minq.addLast(r);
while (!maxq.isEmpty() && a[maxq.peekLast()] <= v) maxq.pollLast();
maxq.addLast(r);
// 收缩直到满足 max - min <= 4
while (!minq.isEmpty() && !maxq.isEmpty() && (a[maxq.peekFirst()] - a[minq.peekFirst()] > 4)) {
if (minq.peekFirst() == l) minq.pollFirst();
if (maxq.peekFirst() == l) maxq.pollFirst();
l++;
}
int len = r - l + 1;
if (len > 0) {
if (len > bestLen) {
bestLen = len;
ans.clear();
ans.add(new int[]{l, r});
} else if (len == bestLen) {
ans.add(new int[]{l, r});
}
}
}
StringBuilder sb = new StringBuilder();
for (int[] p : ans) {
sb.append(p[0]).append(' ').append(p[1]).append('\n');
}
System.out.print(sb.toString());
}
// 简单快速输入
static class FastScanner {
private final InputStream in;
private final byte[] buffer = new byte[1 << 16];
private int ptr = 0, len = 0;
FastScanner(InputStream is) { in = is; }
private int read() throws IOException {
if (ptr >= len) {
len = in.read(buffer);
ptr = 0;
if (len <= 0) return -1;
}
return buffer[ptr++];
}
Integer nextInt() throws IOException {
int c, sgn = 1, x = 0;
do {
c = read();
if (c == -1) return null;
} while (c <= ' ');
if (c == '-') { sgn = -1; c = read(); }
for (; c > ' '; c = read()) {
if (c < '0' || c > '9') break;
x = x * 10 + (c - '0');
}
return x * sgn;
}
}
}
题目内容
某小区宣传其在冬季采暖期间,提供室内温度保持在18−24摄氏度之间,且温差在4摄氏度内的恒温服务。为了评价该小区冬季采暖温控效果,现按固定时间间隔对室内温度进行连续N次采样,采样的室内温度按照从0开始升序的索引号依次记录。
通过计算采样的室内温度在小区承诺恒温范围内的持续时间,即持续时间内的采样室内温度值T均满足 18≤T≤24,且持续时间内的温差(最大温度max - 最低温度min<=4),持续时间越长,采暖温控效果越好。
请输出最大的持续时间开始点和结束点的采样的室内温度索引号,如果存在多个最大持续时间,按持续时间的开始点采样的室内温度索引号升序,逐行输出。
输入描述
第一行输入为按固定时间间隔对室内温度进行连续采样次N。N的取值范围为[1,105]
第二行输入为按固定时间间隔采集的一段连续的室内温度数值,整型,温度数值取值范围[0,30] 。输入格式为:用空格分割的温度数值数组
输出描述
最大持续时间的开始点和结束点的数组元素索引号,中间用空格分隔。存在多组时逐行输出。说明:数组元素索引号从0开始。
样例1
输入
6
16 18 20 25 23 20
输出
1 2
4 5
说明
满足恒温要求的为数组索引1−2、数组索引4−5,按起始索引升序输出
样例2
输入
3
16 18 16
输出
1 1
说明
仅有一个温度18在承诺温度范围内,开始点和结束点的数组元素索引号相同均为1,因此输出1 1
样例3
输入
13
16 18 20 21 22 24 26 25 23 21 21 20 19
输出
8 12
说明
数组中索引1−4温度值为18 20 21 22,均满足18≤T≤24 ,且温差为 22−18=4≤4。持续时间为4;数组中索引8−12温度值为23 21 21 20 19,均满足18≤T≤24 ,且温差为23−19=4≤4 。持续时间为5,因此输出8 12
样例4
输入
11
16 17 18 19 20 21 22 21 22 24 26
输出
2 8