Sliding Window,当数据范围达到1000000时,划分树就已经吃不消了,由于求的是最大和最小,因此用单调队列来维护
这种写法750ms过的,若全部换成scanf和printf就会超时,只换掉scanf 2400ms,可以看出优省出的时间!
#include <iostream>
#include<cstdio>
#include<algorithm>
#include <cstring>
#include <limits.h>
using namespace std;
const int MAX = 1000011;
int a[MAX];
int q[MAX];
int n, m;
//有符号
inline void in(int &d) {
char ch;
int a;
while (ch = getchar(), (ch < 48 || ch > 57) && ch != 45);
ch == 45 ? (d = 0, a = -1) : (d = ch - 48, a = 1);
while (ch = getchar(), ch < 58 && ch > 47) d = d * 10 + ch - 48;
d *= a;
}
/*
//无符号
inline void in(int &d) {
char ch;
while (ch = getchar(), ch < 48 || ch > 57);
d = ch - 48;
while (ch = getchar(), ch < 58 && ch > 47) d = d * 10 + ch - 48;
}
*/
void putint(int n) {
static char buf[32];
register int pos;
register int x = n;
if (x == 0) {
putchar('0');
return;
}
if (x == INT_MIN) { // x = -x do not work for the minimal value of int, so process it first
printf("%d", x);
}
if (x < 0) {
putchar('-');
x = -x;
}
pos = 0;
while (x > 0) {
buf[pos] = x % 10 + '0';
x /= 10;
pos++;
}
pos--;
while (pos >= 0) {
putchar(buf[pos]);
pos--;
}
}
int start, end;
void get_MAX(int i) {
if (start == -1) {
end = start = 0;
q[start] = i;
return;
}
/*自我发明这种写法,简明扼要!!!*/
while (start <= end && i - q[start] >= m) start++;
while (start <= end && a[i] > a[q[end]]) end--;
end++;
q[end] = i;
}
void get_MIN(int i) {
if (start == -1) {
end = start = 0;
q[start] = i;
return;
}
while (start <= end && i - q[start] >= m) start++;
while (start <= end && a[i] < a[q[end]]) end--;
end++;
q[end] = i;
}
int main() {
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 0; i < n; i++) {
in(a[i]);
}
start = end = -1;
for (int i = 0; i < m - 1; i++) {
get_MIN(i);
}
for (int i = m - 1; i < n; i++) {
get_MIN(i);
putint(a[q[start]]);
if (i < n - 1) {
putchar(' ');
} else {
putchar('\n');
}
}
start = end = -1;
for (int i = 0; i < m - 1; i++) {
get_MAX(i);
}
for (int i = m - 1; i < n; i++) {
get_MAX(i);
putint(a[q[start]]);
if (i < n - 1) {
putchar(' ');
} else {
putchar('\n');
}
}
}
return 0;
}
这种写法750ms过的,若全部换成scanf和printf就会超时,只换掉scanf 2400ms,可以看出优省出的时间!
#include <iostream>
#include<cstdio>
#include<algorithm>
#include <cstring>
#include <limits.h>
using namespace std;
const int MAX = 1000011;
int a[MAX];
int q[MAX];
int n, m;
//有符号
inline void in(int &d) {
char ch;
int a;
while (ch = getchar(), (ch < 48 || ch > 57) && ch != 45);
ch == 45 ? (d = 0, a = -1) : (d = ch - 48, a = 1);
while (ch = getchar(), ch < 58 && ch > 47) d = d * 10 + ch - 48;
d *= a;
}
/*
//无符号
inline void in(int &d) {
char ch;
while (ch = getchar(), ch < 48 || ch > 57);
d = ch - 48;
while (ch = getchar(), ch < 58 && ch > 47) d = d * 10 + ch - 48;
}
*/
void putint(int n) {
static char buf[32];
register int pos;
register int x = n;
if (x == 0) {
putchar('0');
return;
}
if (x == INT_MIN) { // x = -x do not work for the minimal value of int, so process it first
printf("%d", x);
}
if (x < 0) {
putchar('-');
x = -x;
}
pos = 0;
while (x > 0) {
buf[pos] = x % 10 + '0';
x /= 10;
pos++;
}
pos--;
while (pos >= 0) {
putchar(buf[pos]);
pos--;
}
}
int start, end;
void get_MAX(int i) {
if (start == -1) {
end = start = 0;
q[start] = i;
return;
}
/*自我发明这种写法,简明扼要!!!*/
while (start <= end && i - q[start] >= m) start++;
while (start <= end && a[i] > a[q[end]]) end--;
end++;
q[end] = i;
}
void get_MIN(int i) {
if (start == -1) {
end = start = 0;
q[start] = i;
return;
}
while (start <= end && i - q[start] >= m) start++;
while (start <= end && a[i] < a[q[end]]) end--;
end++;
q[end] = i;
}
int main() {
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 0; i < n; i++) {
in(a[i]);
}
start = end = -1;
for (int i = 0; i < m - 1; i++) {
get_MIN(i);
}
for (int i = m - 1; i < n; i++) {
get_MIN(i);
putint(a[q[start]]);
if (i < n - 1) {
putchar(' ');
} else {
putchar('\n');
}
}
start = end = -1;
for (int i = 0; i < m - 1; i++) {
get_MAX(i);
}
for (int i = m - 1; i < n; i++) {
get_MAX(i);
putint(a[q[start]]);
if (i < n - 1) {
putchar(' ');
} else {
putchar('\n');
}
}
}
return 0;
}