[POJ2823] [POJ0604月赛] Sliding Window [单调队列/线段树]

大家都知道的单调队列模板题

被卡时间了,难受
poj上G++过不去 只能换C++

简单解释一下,单调队列就是去头(过期信息)+去尾(冗余信息)
放到这题就是每次更新去掉前面加入时间太早的,再去掉后面又早加入又离要求的最值远的

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
using namespace std;
#define getchar() (frS==frT&&(frT=(frS=frBB)+fread(frBB,1,1<<12,stdin),frS==frT)?EOF:*frS++)
char frBB[1<<12]={},*frS=frBB,*frT=frBB;
int N,K,head=1,head2=1;
int lst[1000005]={};
int tme[1000005]={};
int ans[1000005]={};
int lst2[1000005]={};
int tme2[1000005]={};
inline int read()
{
	bool w=0;int x=0;char ch=getchar();
	while(!isdigit(ch))w|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=x*10+(ch-'0'),ch=getchar();
	return w?-x:x;
}
int main()
{
	N=read(); K=read();
	for(register int tmp,i=1;i<=N;++i)
	{
		tmp=read();
		
		lst[0]=lower_bound(lst+head,lst+1+lst[0],-tmp)-lst;
		lst[lst[0]]=-tmp; tme[lst[0]]=i;
		head=upper_bound(tme+head,tme+1+lst[0],i-K)-tme;
		if(i>=K)ans[++ans[0]]=-lst[head];
		
		lst2[0]=lower_bound(lst2+head2,lst2+1+lst2[0],tmp)-lst2;
		lst2[lst2[0]]=tmp; tme2[lst2[0]]=i;
		head2=upper_bound(tme2+head2,tme2+1+lst2[0],i-K)-tme2;
		if(i>=K)printf("%d ",lst2[head2]);
	}
	putchar('\n');
	for(register int i=1;i<=ans[0];++i)printf("%d ",ans[i]);
	return 0;
}

upper_bound和lower_bound有那么慢吗((
不过改成手写二分也是tle

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
using namespace std;
#define getchar() (frS==frT&&(frT=(frS=frBB)+fread(frBB,1,1<<12,stdin),frS==frT)?EOF:*frS++)
char frBB[1<<12]={},*frS=frBB,*frT=frBB;
int N,K,head=1,head2=1;
int lst[1000005]={};
int tme[1000005]={};
int ans[1000005]={};
int lst2[1000005]={};
int tme2[1000005]={};
inline int read()
{
	bool w=0;int x=0;char ch=getchar();
	while(!isdigit(ch))w|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=x*10+(ch-'0'),ch=getchar();
	return w?-x:x;
}
int lowb(int* array,int l,int r,int key)
{
	register int mid; ++r;
	while(l<r)
	{
		mid=l+r>>1;
		if(array[mid]<key)l=mid+1;
		else r=mid;
	}
	return l;
}
int main()
{
	N=read(); K=read();
	for(register int tmp,i=1;i<=N;++i)
	{
		tmp=read();
		
		lst[0]=lowb(lst,head,lst[0],-tmp);
		lst[lst[0]]=-tmp; tme[lst[0]]=i;
		while(tme[head]<=i-K)++head; //这里上面的代码不该二分的
		if(i>=K)ans[++ans[0]]=-lst[head];
		
		lst2[0]=lowb(lst2,head2,lst2[0],tmp);
		lst2[lst2[0]]=tmp; tme2[lst2[0]]=i;
		while(tme2[head2]<=i-K)++head2;
		if(i>=K)printf("%d ",lst2[head2]);
	}
	putchar('\n');
	for(register int i=1;i<=ans[0];++i)printf("%d ",ans[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Estia_/article/details/82953034