题意
给你n个数和一个区间的长度k,求从前往后每个[i,i+k-1] (1<=i<=n-k+1)区间的最大值和最小值。
题解
用单调队列搞一搞,然后。。。然后就超时了,学习了一下可以二分出队列,就去弄了一下二分(其实k不大的话二分也没啥用啊)。然后。。。然后就超时了。
好吧为什么G++就是会超时呢?用C++就过了。
代码
#include<cstdio>
#include <iostream>
#include<algorithm>
#include<string.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
int n, m;
int a[N];
int que[N]; //队列中a[i]的下标
int qu[N];
int Max[N];
int Min[N];
void getMax()
{
int head=1,rear=0;
for(int i=1;i <= n;i++)
{
if(rear>=head&&a[que[rear]]<=a[i]) {
int r = rear, l = head;
int mid;
while(l < r)
{
mid = (l+r)>>1;
if(a[que[mid]] <= a[i])
r = mid;
else if(a[que[mid]] > a[i])
l = mid+1;
}
rear = l;
que[rear] = i;
}
else
que[++rear]=i; //插入到这个位置
if(i>=m) {
if(que[head]<i-m+1) {
int r = rear, l = head;
int mid;
while(l < r)
{
mid = (l+r)>>1;
if(que[mid] >= i-m+1)
r = mid;
else if(que[mid] < i-m+1)
l = mid+1;
}
head = l;
}
Max[i-m+1] = a[que[head]];
}
}
}
void getMin()
{
int head = 1, rear = 0;
for(int i = 1; i <= n; i++)
{
if(rear>=head&&a[que[rear]]>=a[i]) {
int r = rear, l = head;
int mid;
while(l < r)
{
mid = (l+r)>>1;
if(a[que[mid]] >= a[i])
r = mid;
else if(a[que[mid]] < a[i])
l = mid+1;
}
rear = l;
que[rear] = i;
}
else
que[++rear] = i;
if(i>=m) {
if(que[head]<i-m+1) {
int r = rear, l = head;
int mid;
while(l < r)
{
mid = (l+r)>>1;
if(que[mid] >= i-m+1)
r = mid;
else if(que[mid] < i-m+1)
l = mid+1;
}
head = l;
}
Min[i-m+1] = a[que[head]];
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
getMin();
getMax();
for(int i = 1; i < n-m+1; i++)
printf("%d ", Min[i]);
printf("%d\n", Min[n-m+1]);
for(int i = 1; i < n-m+1; i++)
printf("%d ", Max[i]);
printf("%d\n", Max[n-m+1]);
return 0;
}