題目描述
題解
去年Apio回來寫了這道題,今天看被ATP和hxy兩位大爺怒切了,於是趕來補一發題解
30pts
注意到是“嚴格上升”的序列
每一次查詢當前區間的mn,mx,然後左右指針往裏縮,這樣就能在
70pts
首先查詢一下整個定義域,找到整個數列的mn和mx
將[mn,mx]劃分成N塊,每塊長度爲
可以發現最大值一定不會出現在塊內,跨塊的話一定是一個塊的最大值和另一個塊的最小值
所以對於每一個塊找mn和mx就行了
這樣的話,最大值和最小值點被查詢了1次,剩餘的點被查詢了2次,而總的查詢次數是N+1,所以費用爲2+(N-2)*2+N+1=3N-1,正好符合要求
代碼
#include "gap.h"
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long a[500005]={0};
long long findGap(int T, int N)
{
if (T==1)
{
int l=1,r=N;
long long Min=0,Max=1e18,mn,mx,ans=0;
while (l<=r)
{
MinMax(Min,Max,&mn,&mx);
a[l]=mn; a[r]=mx;
l++; r--;
Min=mn+1; Max=mx-1;
}
for (int i=1;i<N;++i)
if (ans<a[i+1]-a[i])
ans=a[i+1]-a[i];
return ans;
}
else
{
long long Min=0,Max=1e18,mn,mx,L,l,r,ans=0;
bool flag=false;
int n=0;
MinMax(Min,Max,&mn,&mx);
if ((mx-mn)%N!=0) L=(mx-mn)/N+1;
else L=(mx-mn)/N;
Min=mn; Max=mx-1; a[++n]=mn;
while (!flag)
{
l=Min+1;
r=Min+L;
if (r>=Max)
{
r=Max;
flag=true;
}
if (l<=r) MinMax(l,r,&mn,&mx);
if (mn!=-1&&mx!=-1)
a[++n]=mn,a[++n]=mx;
Min+=L;
}
a[++n]=Max+1;
for (int i=1;i<n;++i)
if (ans<a[i+1]-a[i])
ans=a[i+1]-a[i];
return ans;
}
}