首页 > 代码库 > BZOJ2096: [Poi2010]Pilots

BZOJ2096: [Poi2010]Pilots

2096: [Poi2010]Pilots

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 270  Solved: 142
[Submit][Status]

Description

Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值。耍畸形一个人是不行的,于是他找到了你。

Input

输入:第一行两个有空格隔开的整数k(0<=k<=2000,000,000),n(1<=n<=3000,000),k代表Tz设定的最大值,n代表难度序列的长度。第二行为n个由空格隔开的整数ai(1<=ai<=2000,000,000),表示难度序列。

Output

输出:最大的字串长度。

Sample Input

3 9
5 1 3 5 8 6 6 9 10

Sample Output

4
(有两个子串的长度为4: 5, 8, 6, 6 和8, 6, 6, 9.最长子串的长度就是4)

HINT

 

Source

by poi

题解:
此题做的好艰辛,大神们都说是水题T_T
首先肯定是单调队列,然后我想的是枚举每一个可行区间的最小值,找出它向左向右更能拓展多少?
结果发现做不出来T_T
然后去膜拜wyx528的题解,发现我的思路就错了:
 

我们考虑顺序枚举序列的右端点 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 100000000013 #define maxn 300000514 #define maxm 500+10015 #define eps 1e-1016 #define ll long long17 #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 100000000723 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 }
View Code

 

 

BZOJ2096: [Poi2010]Pilots