[UOJ#206][Apio2016]Gap(分塊+數學相關)

題目描述

傳送門

題解

去年Apio回來寫了這道題,今天看被ATP和hxy兩位大爺怒切了,於是趕來補一發題解

30pts

注意到是“嚴格上升”的序列
每一次查詢當前區間的mn,mx,然後左右指針往裏縮,這樣就能在N+12 的次數之內得到整個序列

70pts

首先查詢一下整個定義域,找到整個數列的mn和mx
將[mn,mx]劃分成N塊,每塊長度爲mxmnN
可以發現最大值一定不會出現在塊內,跨塊的話一定是一個塊的最大值和另一個塊的最小值
所以對於每一個塊找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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章