首页 > 代码库 > BZOJ2096: [Poi2010]Pilots
BZOJ2096: [Poi2010]Pilots
2096: [Poi2010]Pilots
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 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
5 1 3 5 8 6 6 9 10
Sample Output
4
(有两个子串的长度为4: 5, 8, 6, 6 和8, 6, 6, 9.最长子串的长度就是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 }
BZOJ2096: [Poi2010]Pilots
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。