题目描述
一个含有 nnn 项的数列,求出每一项前的 mmm 个数到它这个区间内的最小值。若前面的数不足 mmm 项则从第 111 个数开始,若前面没有数则输出 000。
输入格式
第一行两个整数,分别表示 nnn,mmm。
第二行,nnn 个正整数,为所给定的数列 aia_iai。
输出格式
nnn 行,每行一个整数,第 iii 个数为序列中 aia_iai 之前 mmm 个数的最小值。
输入输出样例
输入 #1
6 2
7 8 1 4 3 2
输出 #1
0
7
7
1
1
3
说明/提示
对于 100%100%100% 的数据,保证 1≤m≤n≤2×1061\le m\le n\le2\times10^61≤m≤n≤2×106,1≤ai≤3×1071\le a_i\le3\times10^71≤ai≤3×107。
题意:求滑动窗口的里的最小值
解法一 : 单调队列 O(N)
用双端队列deque
模拟窗口
- deque里存储结构体
{下标,值}
- 先把所有队尾
back
比当前值a[i]
大的全部弹出,while(back > a[i]) deque.pop_back()
a[i]
入队列,deque.push_back(a[i])
- 如果队头的下标
front_id
不在窗口区间[i-m, i]
内就弹出队头
洛谷大佬@lcglcg
的题解:https://www.luogu.com.cn/blog/lcglcg/solution-p1440
signed main() {
#ifdef debug
freopen("test.txt", "r", stdin);
clock_t stime = clock();
#endif
scanf("%d %d ", &n, &m);
for(int i=1; i<=n; i++) scanf("%d ", a+i);
deque<pair<int,int> > q; //deque模拟窗口
printf("0\n");
for(int i=1; i<n; i++) {
//先把队尾大于a[i]的弹出干净
while(!q.empty() && q.back().second>a[i]) q.pop_back();
q.push_back({
i, a[i]}); //压入队尾
//再把队头所有不在区间 [i-m, i] 内的弹出干净
while(!q.empty() && q.front().first+m<=i) q.pop_front();
printf("%d\n", q.front().second);
}
#ifdef debug
clock_t etime = clock();
printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif
return 0;
}
解法二:小根堆优化 O(N log N)
用priority_queue
模拟窗口,
堆
里存储结构体{下标,值}
- 压入值后,把所有
不在窗口区间[i-m, i]
内的堆顶弹出
signed main() {
#ifdef debug
freopen("test.txt", "r", stdin);
clock_t stime = clock();
#endif
scanf("%d %d ", &n, &m);
#if 1
for(int i=1; i<=n; i++) scanf("%d ", a+i);
// show(n, m);
// forarr(a, 1, n);
#define PII (pair<int,int>)
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int> > > q;
printf("0\n");
for(int i=1; i<n; i++) {
#define fstid (q.front().first)
#define fstval (q.front().second)
#define topval (q.top().first)
#define topid (q.top().second)
q.push({
a[i], i});
while(topid <= i-m) q.pop();
printf("%d\n", topval);
}
#endif
#ifdef debug
clock_t etime = clock();
printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif
return 0;
}
用java完美MLE
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static final boolean debug = true;
public static String INPATH = "C:\\Users\\majiao\\Desktop\\test.txt",
OUTPATH = "C:\\Users\\majiao\\Desktop\\out.txt";
public static StreamTokenizer tok;
public static BufferedReader cin;
public static PrintWriter cout;
public static long start_time = 0, out_time = 0;
public static