zoukankan      html  css  js  c++  java
  • UOJ#206. 【APIO2016】Gap 构造 交互题

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ206.html

    题解

    T = 1 的情况直接大力从两边向中间询问即可。

    T = 2 的情况挺妙的,我没想到。

      考虑首先花费 n + 1 代价得到全局最大值和最小值,也就是 a[1] 和 a[n] 。

      然后考虑将值域均分为 n - 1 段,每一段询问一下。答案一定在 相邻两段区间的 左边一段的Max 和右边一段的Min 之间 ,或者 a[1] 与 a[1] 右侧数,或者 a[n] 与 a[n] 左侧数 中产生。

      我们考虑证明这个东西:

      设每一段的长度 $d = left lceil frac {a[n] - a[1]}{n-1} ight ceil$ ,如果答案在某一段区间中,那么 $ans leq d - 2$。然而,根据抽屉原理,总共有 $a[n] - a[1] - 1 - (n-2)$ 个空位,分成 $n-1$ 段,那么最长的一段至少长度为 $left lceil frac{a[n] - a[1] - 1 - (n-2) } { n-1 } ight ceil = d-1 > d - 2$,故答案不可能在某一段区间内。

      接下来证明一下我们的花费在 $3n$ 之内。

      1. 第一次询问花费 n + 1 。

      2. 接下来询问不超过 n - 1 次。

      3. 询问到的数字个数不超过 n - 2 。

      所以总询问次数的上线是 $3n - 2$ ,可以通过此题。

    代码

    #include <bits/stdc++.h>
    #define For(i,a,b) for (int i=a;i<=b;i++)
    #include "gap.h"
    using namespace std;
    typedef long long LL;
    const int N=100005;
    LL a[N];
    LL findGap(int type,int n){
    	if (type==1){
    		int lp=1,rp=n;
    		LL lv=0,rv=1e18,Min,Max;
    		while (lp<=rp){
    			MinMax(lv,rv,&Min,&Max);
    			a[lp++]=Min;
    			a[rp--]=Max;
    			lv=Min+1,rv=Max-1;
    		}
    		LL res=0;
    		For(i,1,n-1)
    			res=max(res,a[i+1]-a[i]);
    		return res;
    	}
    	else {
    		LL lv,rv,ans=0;
    		MinMax(0,1e18,&lv,&rv);
    		LL d=(rv-lv+(n-2))/(n-1),pre=lv;
    		for (;lv<rv-1;lv+=d){
    			LL Min,Max;
    			MinMax(lv+1,min(lv+d,rv-1),&Min,&Max);
    			if (Min!=-1){
    				ans=max(ans,Min-pre);
    				pre=Max;
    			}
    		}
    		ans=max(ans,rv-pre);
    		return ans;
    	}
    }
    

      

  • 相关阅读:
    链表问题
    有关动态规划的LeetCode
    正则表达式匹配与自动机
    基于数据库范式的一点点想法
    html5 API
    Web鼠标事件
    webpack模块化原理
    Jquery数据缓存
    图片懒加载
    MySql存储过程的调试
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ206.html
Copyright © 2011-2022 走看看