1369 窗口超级版

来源:互联网 发布:wifi提示无法加入网络 编辑:程序博客网 时间:2024/04/29 16:35
 
描述

有一串整数在排队……

有N个整数,你有一个可以框住M个连续段整数的木框,现在你想知道,对于这个队列中任意的连续M个整数,最大和最小的整数是哪个?

例:(M大小的窗口向右滑动)

1 2 3 2 1 M=2

1 2 MAX 2 MIN 1

2 3 MAX 3 MIN 2

3 2 MAX 3 MIN 2

2 1 MAX 2 MIN 1

最后需要输出的是两行:

1 2 2 1

2 3 3 2

输入

第一行包含一个整数T,表示有T组测试数据;

以下每组测试数据格式:

第一行包含2个整数N,M表示有N个整数在排队,取连续M个整数。

第二行包含N个整数。

其中N不大于1,000,000,M不大于N。

输出

按照题目描述格式输出结果,第一行为MIN,第二行为MAX。

样例输入
1 
5 2 
1 2 3 2 1 
样例输出
1 2 2 1 
2 3 3 2
提示

注意数据规模!

 

明显简单的方法无效,数据规模很大,这里用线段树来做,也可以来看http://blog.tomtung.com/ 博客,其中有更好的解法

#include<iostream>#include<queue>#include<vector>using namespace std;const int M = 1000010;int A[M], mi[M], ma[M];struct Cmpa{bool operator ()(const int &a, const int &b){return A[a] < A[b];}};struct Cmpi{bool operator ()(const int &a, const int &b){return A[a] > A[b];}};priority_queue<int, vector<int>, Cmpi> qi;priority_queue<int, vector<int>, Cmpa> qa;int main(){int i, j, k, n, m, t, l;scanf("%d", &t);while(t--) {scanf("%d%d", &n, &m);for(i = 0; i < n; i++) scanf("%d", &A[i]);for(i = 0; i < m-1; i++) {qi.push(i); qa.push(i);}l = 0;for(i = m-1; i < n; i++) {qi.push(i); qa.push(i);while(i - qi.top() >= m) qi.pop();while(i - qa.top() >= m) qa.pop();mi[l] = A[qi.top()];ma[l++] = A[qa.top()];}for(i = 0; i < l-1; i++) printf("%d ", mi[i]);printf("%d\n", mi[i]);for(i = 0; i < l-1; i++) printf("%d ", ma[i]);printf("%d\n", ma[i]);}return 0;}


 

原创粉丝点击