Sound静音问题 bzoj-1342 Baltic-2007
题目大意:给定一个n个数的序列,求所有的长度为m的区间,使得区间内最大值减去最小值不超过阈值c。
注释:$1le n le 10^6$,$1le mle 10^4$。
想法:单调队列裸题。
定长区间最值问题显然可以用单调队列维护。
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 1001000 #define inf 0x3f3f3f3f using namespace std; int id1[N],x1[N],l1,r1; int id2[N],x2[N],l2,r2; int n,m,p,s[N]; int main() { scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n;i++)scanf("%d",&s[i]); l1=l2=1,r1=r2=0; int flag=1; for(int i=1;i<=n;i++) { while(l1<=r1&&i-id1[l1]>=m)l1++; while(l2<=r2&&i-id2[l2]>=m)l2++; while(l1<=r1&&s[i]>=x1[r1])r1--; while(l2<=r2&&s[i]<=x2[r2])r2--; id1[++r1]=id2[++r2]=i; x1[r1]=x2[r2]=s[i]; if(i>=m)if(x1[l1]-x2[l2]<=p) printf("%d ",i-m+1),flag=0; } if(flag)puts("NONE"); return 0; }
小结:单调队列内是两个关键字,一个关键字随下标递增而变优,另一关键字随下标递增而变劣。