2096: [Poi2010]Pilots
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 438 Solved: 219
[Submit][Status][Discuss]
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
这道题有两种做法。。可以二分长度然后单调队列验证。。也可以用堆做。。
堆:
从头到尾枚举每一个元素,将其分别加入大根堆和小根堆中。。然后维护一个右边界表示没有冲突的最右边的位置。。如果发现有冲突了,就调整右边界的位置,然后将堆中不在范围里的元素弹出。
#include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 3000010; struct data{int val,id;}; int a[N],n,K,ans; bool operator < (data a,data b){return a.val<b.val;} int read(){ int x = 0,f = 1,c = getchar(); while (c<'0' || c>'9'){if (c=='-') f = -1;c = getchar();} while (c>='0' && c<='9') x = x*10+c-'0',c = getchar(); return x*f; } priority_queue<data> q1,q2; void solve(){ int l = 1; for (int i=1;i<=n;i++){ q1.push((data){a[i],i}); q2.push((data){-a[i],i}); while (q1.top().val+q2.top().val>K){ l++; while (!q1.empty() && q1.top().id<l) q1.pop(); while (!q2.empty() && q2.top().id<l) q2.pop(); } ans = max(ans,i-l+1); } } int main(){ K = read();n = read(); for (int i=1;i<=n;i++) a[i] = read(); solve(); printf("%d",ans); }