题目要输出一个序列各个长度k的连续子序列的最大值最小值。
多次RMQ的算法也是能过的,不过单调队列O(n)。
这题,队列存元素值以及元素下标,队尾出队维护单调性然后入队,队首出队保持新元素下标与队首元素下标差小于k。
以前写的还是3个if-else,重写了下。。不加输出挂会T。。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 #define MAXN 1111111 5 inline void in(int &ret){ 6 char c; int sgn; 7 while(c=getchar(),c!='-'&&(c<'0'||c>'9')) if(c==EOF) return; 8 sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); 9 while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); 10 ret*=sgn; 11 } 12 void out(int x){ 13 if(x<0){ 14 putchar('-'); out(-x); 15 return; 16 } 17 if(x>9) out(x/10); 18 putchar(x%10+'0'); 19 } 20 int que[MAXN],idx[MAXN],front,rear; 21 int a[MAXN]; 22 int main(){ 23 int n,k; 24 in(n); in(k); 25 for(int i=1; i<=n; ++i){ 26 in(a[i]); 27 } 28 for(int i=1; i<=n; ++i){ 29 if(front!=rear && idx[front]+k<=i) ++front; 30 while(front!=rear && que[rear-1]>=a[i]) --rear; 31 idx[rear]=i; que[rear]=a[i]; ++rear; 32 if(i>=k){ 33 out(que[front]); putchar(' '); 34 } 35 } 36 putchar(' '); 37 front=rear=0; 38 for(int i=1; i<=n; ++i){ 39 if(front!=rear && idx[front]+k<=i) ++front; 40 while(front!=rear && que[rear-1]<=a[i]) --rear; 41 idx[rear]=i; que[rear]=a[i]; ++rear; 42 if(i>=k){ 43 out(que[front]); putchar(' '); 44 } 45 } 46 return 0; 47 }