1. 程式人生 > >【bzoj2096】[Poi2010]Pilots 雙指針法+STL-set

【bzoj2096】[Poi2010]Pilots 雙指針法+STL-set

sca scan sof microsoft 區間最值 bzoj turn 區間 color

題目描述

Tz又耍畸形了!!他要當飛行員,他拿到了一個飛行員測試難度序列,他設定了一個難度差的最大值,在序列中他想找到一個最長的子串,任意兩個難度差不會超過他設定的最大值。耍畸形一個人是不行的,於是他找到了你。

輸入

輸入:第一行兩個有空格隔開的整數k(0<=k<=2000,000,000),n(1<=n<=3000,000),k代表Tz設定的最大值,n代表難度序列的長度。第二行為n個由空格隔開的整數ai(1<=ai<=2000,000,000),表示難度序列。

輸出

輸出:最大的字串長度。

樣例輸入

3 9
5 1 3 5 8 6 6 9 10

樣例輸出

4


題解

雙指針法+STL-set

考慮隨著做端點向右移動,右端點的選擇是單調不降的。所以可以使用雙指針法掃出以某個點為左端點的最長的區間。

此時需要維護區間最值,可以使用單調隊列來在線性時間內解決。當然本題也可以像我一樣使用set水過。

#include <cstdio>
#include <set>
using namespace std;
multiset<int> s;
int a[3000010];
int main()
{
	int k , n , i , p , ans = 0;
	scanf("%d%d" , &k , &n);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
	for(i = p = 1 ; i <= n ; i ++ )
	{
		while(p <= n && (s.empty() || max(*(--s.end()) , a[p]) - min(*s.begin() , a[p]) <= k)) s.insert(a[p ++ ]);
		ans = max(ans , p - i) , s.erase(s.find(a[i]));
	}
	printf("%d\n" , ans);
	return 0;
}

【bzoj2096】[Poi2010]Pilots 雙指針法+STL-set