UOJ#206. 【APIO2016】Gap

题目描述

传送门

题解

人生第一道交互题!!!

子任务1:要求查询的次数不超过 n+12
每次查询得到数列的最小值和最大值,然后将询问的区间左右端点同是向内缩小1,继续查询,除了最后一次询问,剩下的询问每次可以得到两个数值,那么我们一定可以在 n+12 次询问内得到每一个数的值。

子任务2:定义 k 为调用 MinMax 时,区间 [s,t] 中的序列中数的数量。每次调用 MinMax,将使 M 加上 k+1 。对于每一个测试点,如果 M3N ,你将得到 70 分,否则将得到 60MN+11
先花费 n+1 的代价得到数列中的最大值 l 和最小值 r
然后将 [l+1,r1] 均分成 n2 个权值区间。那么有两种情况。
第一种情况: n2 个区间中每个区间都有数,那么每个区间有且仅有一个数,我们可以用 n2 次询问,花费 n+n2 得到所有的数,然后统计答案,
第二种情况:存在区间中一个数也没有,那么答案一定会大于均分的区间长度,所有我们不关心每个区间中具体的数,只要考虑是区间最值的且相邻的数,然后更新答案,不要忘记统计最初最大值最小值的贡献,花费与询问的次数与第一种情况是一样的。

代码

#include "gap.h"
#include
#include
#include
#include
using namespace std;
const long long inf=1e18;
long long findGap(int T,int N)
{
    long long ans=0;
    if (T==1) {
        long long mn1,mx1; MinMax(0,inf,&mn1,&mx1);
        if (N==1) ans=0;
        int tmp=N-2; if (tmp==0) ans=max(ans,mx1-mn1);
        while (tmp>0) {
            long long mn,mx;
            if (mn1+1<=mx1-1) MinMax(mn1+1,mx1-1,&mn,&mx);
            else break;
            ans=max(ans,max(mn-mn1,mx1-mx));
            if (tmp==2) ans=max(ans,mx-mn);
            if (mn==mx) tmp--;
            else tmp-=2;
            mn1=mn; mx1=mx;
        }
        return ans;
    }
    if (T==2) {
        long long l,r; MinMax(0,inf,&l,&r);
        if (N==2||N==1) return r-l;
        long long len=(r-l-1)/(N-2)+1; long long last=l;
        long long s=l+1,t;
        for (int i=1;i<=N-2;i++) {
            t=min(s+len-1,r-1);
            if (s>t) break;
            long long mn,mx; MinMax(s,t,&mn,&mx);
            if (mn!=-1) {
                ans=max(ans,mn-last);
                last=mx;
            }
            s=t+1;
        }
        ans=max(ans,r-last);
        return ans;
    }
}

你可能感兴趣的:(乱搞)