大家好,又见面了,我是你们的朋友全栈君。
Sliding Window
题目传送:POJ – 2823 – Sliding Window
闲来没事学学单调队列的写法,嗯,一个很奇怪的队列形式。。
单调队列是指:队列中元素之间的关系具有单调性,而且,队首和队尾都可以进行出队操作,只有队尾可以进行入队操作。
因为这里是滑动窗口,每次移动需要进行更新,所以可以用单调队列来实现。
本题用单调递增队列来求每一个区间的最小值,用单调递减队列来求每一个区间的最大值,用一个pos数组记录单调队列里每一个数出现的位置来比较是否要更新(即删去)
具体实现还是看代码吧。
AC代码:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;
const int maxn = 1000005;
int a[maxn];
int Min[maxn];//记录每个窗口最小答案
int Max[maxn];//记录每个窗口最大答案
int que[maxn];//数组模拟单调队列
int pos[maxn];//记录位置,用来更新
int n, k;
void get_min() {
//维护单调递增队列,队头为最小
int head = 0, rear = 0;
for(int i = 1; i < k; i ++) {
//先将前k-1个放入队列
while(rear > head && que[rear - 1] > a[i]) rear --;
que[rear] = a[i];
pos[rear] = i;
rear ++;
}
for(int i = k; i <= n; i ++) {
while(rear > head && que[rear - 1] > a[i]) rear --;
que[rear] = a[i];
pos[rear] = i;
rear ++;
while(pos[head] < i - k + 1) head ++;//因为是滑窗,所以要及时更新
Min[i] = que[head];
}
}
void get_max() {
//维护单调递减队列,队头为最大
int head = 0, rear = 0;
for(int i = 1; i < k; i ++) {
//先将前k-1个放入队列
while(rear > head && que[rear - 1] < a[i]) rear --;
que[rear] = a[i];
pos[rear] = i;
rear ++;
}
for(int i = k; i <= n; i ++) {
while(rear > head && que[rear - 1] < a[i]) rear --;
que[rear] = a[i];
pos[rear] = i;
rear ++;
while(pos[head] < i - k + 1) head ++;//因为是滑窗,所以要及时更新
Max[i] = que[head];
}
}
int main() {
while(scanf("%d %d", &n, &k) != EOF) {
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
}
get_min();
get_max();
for(int i = k; i < n; i ++) {
printf("%d ", Min[i]);
}
printf("%d\n", Min[n]);
for(int i = k; i < n; i ++) {
printf("%d ", Max[i]);
}
printf("%d\n", Max[n]);
}
return 0;
}
Subsequence
AC代码:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;
const int maxn = 100005;
int n, m, k;
int a[maxn];
int q1[maxn], q2[maxn];//单调队列记录最大和最小的位置
int head1, rear1;
int head2, rear2;
int main() {
while(scanf("%d %d %d", &n, &m, &k) != EOF) {
head1 = rear1 = 0;
head2 = rear2 = 0;
int pre = 1;//记录可行区间的最左,i可以动态表示可行区间的最右
int ans = 0;
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
while(rear1 > head1 && a[q1[rear1 - 1]] < a[i]) rear1 --;
while(rear2 > head2 && a[q2[rear2 - 1]] > a[i]) rear2 --;
q1[rear1 ++] = i;
q2[rear2 ++] = i;
while(rear1 > head1 && rear2 > head2 && a[q1[head1]] - a[q2[head2]] > k) {
//更新可行区间的最左
if(q1[head1] > q2[head2]) pre = q2[head2 ++] + 1;
else pre = q1[head1 ++] + 1;
}
if(rear1 > head1 && rear2 > head2 && a[q1[head1]] - a[q2[head2]] >= m) {
//此区间的最大最小满足在m,k之间,所以更新答案
ans = max(ans, i - pre + 1);//更新答案
}
}
printf("%d\n", ans);
}
return 0;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/153003.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...