题目链接:http://poj.org/problem?id=2823
题意:有N个数字排成一行,,编号1....N。然后有个宽度为K的滑动窗口,这个窗口的左侧开始停在编号为1的数字
,每次向右滑动一个数字,直至窗口的右侧停在编号为N的数字,每次滑动(包括第一次没滑动),查询窗口里包含的数字中最大的一个和最小的一个。输出时,一行先输出所有最小的,然后另起一行输出所有最大的。
注意:如果你是用的线段树循环求解的方法做的话,提交时选择C++编译器,而不要使用G++编译器,否则会报TLE。因为G++,我可以得到了7次TLE的,一换C++,立马就过了,虽然时间很慢。
代码:
#include<stdio.h>
#define MAXN 1000005
struct Node{
int left;
int right;
int max;
int min;
}node[MAXN*4];
int hei[MAXN];
int N,k;
int ansmax,ansmin;
int ans1[MAXN],ans2[MAXN];
int id1;
int Max(int a,int b)
{
return a>b ? a : b ;
}
int Min(int a,int b)
{
return a<b ? a : b ;
}
void BuildTree(int left,int right,int tot)
{
node[tot].left = left;
node[tot].right = right;
if(left == right)
{
node[tot].max = node[tot].min = hei[left];
return ;
}
BuildTree(left,(left+right)/2,tot*2);
BuildTree((left+right)/2+1,right,tot*2+1);
node[tot].max = Max(node[tot*2].max,node[tot*2+1].max);
node[tot].min = Min(node[tot*2].min,node[tot*2+1].min);
}
void Query(int left,int right,int tot)
{
if(node[tot].left == left && node[tot].right == right)
{
ansmax = Max(ansmax,node[tot].max);
ansmin = Min(ansmin,node[tot].min);
return ;
}
int mid=(node[tot].left+node[tot].right)/2;
if (mid>=right) Query(left,right,tot*2);
else if (mid<left) Query(left,right,tot*2+1);
else
{
Query(left,mid,tot*2);
Query(mid+1,right,tot*2+1);
}
}
int main()
{
while(scanf("%d%d",&N,&k)!=EOF)
{
int i;
for(i=1;i<=N;i++)
{
scanf("%d",&hei[i]);
}
BuildTree(1,N,1);
for(i=1;i<=N-k+1;i++)
{
/* if(ans1[i-1] != hei[i-1] && ans2[i-1] != hei[i-1])
{
ans1[i]=Min(ans1[i-1],hei[i+k-1]);
ans2[i]=Max(ans2[i-1],hei[i+k-1]);
}
else
{*/
ansmax = -10000000;
ansmin = 10000000;
Query(i,i+k-1,1);
ans2[i] = ansmax;
ans1[i] = ansmin;
}
for(i=1;i<=N-k+1;i++)
{
printf("%d ",ans1[i]);
}
printf("\n");
for(i=1;i<=N-k+1;i++)
{
printf("%d ",ans2[i]);
}
printf("\n");
}
return 0;
}