标签:des style blog http color io os ar for
我们考虑顺序枚举序列的右端点 i,设在位置 i 处,取得最长合法序列的左端点为 L[i],易证随着 i 的增加
L[i]单调不减,于是开两个单调队列维护最大值和最小值即可,注意一下内存限制。时间复杂度 O(n)。
然后就是实现的问题了,首先必须先插入,然后不合题意的时候怎么删除呢?
yy了好久yy出了这样的操作:
1 f[i]=f[i-1]; 2 while(a[q[0][l[0]]]-a[q[1][l[1]]]>k) 3 f[i]=q[0][l[0]]<q[1][l[1]]?q[0][l[0]++]+1:q[1][l[1]++]+1; 4 ans=max(ans,i-f[i]+1);
f[i]代表着左区间端点。
注意各变量所代表的实际含义。
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 3000005 14 #define maxm 500+100 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define mod 1000000007 23 using namespace std; 24 inline int read() 25 { 26 int x=0,f=1;char ch=getchar(); 27 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 28 while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();} 29 return x*f; 30 } 31 int n,k,l[2],r[2],a[maxn],f[maxn],q[2][maxn]; 32 int main() 33 { 34 freopen("input.txt","r",stdin); 35 freopen("output.txt","w",stdout); 36 k=read();n=read(); 37 for1(i,n)a[i]=read(); 38 int ans=1; 39 l[0]=l[1]=1;f[0]=1; 40 for1(i,n) 41 { 42 while(l[0]<=r[0]&&a[q[0][r[0]]]<=a[i])r[0]--; 43 q[0][++r[0]]=i; 44 while(l[1]<=r[1]&&a[q[1][r[1]]]>=a[i])r[1]--; 45 q[1][++r[1]]=i; 46 f[i]=f[i-1]; 47 while(a[q[0][l[0]]]-a[q[1][l[1]]]>k) 48 f[i]=q[0][l[0]]<q[1][l[1]]?q[0][l[0]++]+1:q[1][l[1]++]+1; 49 ans=max(ans,i-f[i]+1); 50 } 51 printf("%d\n",ans); 52 return 0; 53 }
标签:des style blog http color io os ar for
原文地址:http://www.cnblogs.com/zyfzyf/p/4008295.html