UOJ#206. 【APIO2016】Gap

来源:互联网 发布:康麻子 知乎 编辑:程序博客网 时间:2024/06/06 08:37

题目描述

传送门

题解

人生第一道交互题!!!

子任务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<iostream>#include<cstdio>#include<cstring>#include<algorithm>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;    }}
0 0
原创粉丝点击