UOJ #206. 【APIO2016】Gap 交互题+乱搞

题意

有 N 个严格递增的非负整数 a1,a2,…,aN(0≤a1 < a2 < ⋯ < aN≤10^18)。你需要找出 ai+1−ai(0≤i≤N−1)里的最大的值。

你的程序不能直接读入这个整数序列,但是你可以通过给定的函数来查询该序列的信息。关于查询函数的细节,请根据你所使用的语言,参考下面的实现细节部分。

对于子任务1,每次调用M+1 M n + 1 2
对于子任务2,每次调用假设区间内有k个整数,M+=k+1 M 3 N

分析

首先对于子任务1还是很简单的,每次找两个,不断缩小范围

对于子任务2考虑分治的方法?,考虑到只要找最大值,那么把最前面的和最后面的找出来,中间的答案至少有 t s n 1 这么大, 那么我们以这个间隔来跳,最多跳n个区间,然后最多找到n个数,所以有3n做法

代码

#include <bits/stdc++.h>
#include "gap.h"
using namespace std;
#define pb push_back

typedef long long ll;

const ll inf = 1e18;

ll a[100010];

ll findGap(int T, int N)
{
  vector<ll> v;
  if(T==1)
  {
    ll ml = 1; ll mr = N; a[0] = -1; a[N+1] = inf+1;
    while(ml <= mr)
    {
      ll mn , mx;
      MinMax(a[ml-1] + 1, a[mr+1] - 1, &a[ml], &a[mr]);
      ml++; mr--;
    }
    ll ans = 0;
    for(ll i=2;i<=N;i++) ans = max(a[i] - a[i-1] , ans);

    return ans;
  }
  else
  {
    ll s,t; MinMax(0,inf,&s,&t);
    ll delta = (t-s) / (N-1); ll ans = delta;
    ll x=s;
    for(ll i=s+1;i<=t;i+=delta+1)
    {
      ll mn , mx;
      MinMax(i,i+delta,&mn,&mx);
      if(mn!=-1) ans = max(ans , mn - x) , x = mx;
    }
    return ans;
  }

  return 0;
}

/*#include <bits/stdc++.h>
#define pb push_back
using namespace std;

typedef long long ll;

static void my_assert(int k){ if (!k) exit(1); }

static int subtask_num, N;
static long long A[100001];
static long long call_count;

void MinMax(long long s, long long t, long long *mn, long long *mx)
{
    int lo = 1, hi = N, left = N+1, right = 0;
    my_assert(s <= t && mn != NULL && mx != NULL);
    while (lo <= hi){
        int mid = (lo+hi)>>1;
        if (A[mid] >= s) hi = mid - 1, left = mid;
        else lo = mid + 1;
    }
    lo = 1, hi = N;
    while (lo <= hi){
        int mid = (lo+hi)>>1;
        if (A[mid] <= t) lo = mid + 1, right = mid;
        else hi = mid - 1;
    }
    if (left > right) *mn = *mx = -1;
    else{
        *mn = A[left];
        *mx = A[right];
    }
    if (subtask_num == 1) call_count++;
    else if (subtask_num == 2) call_count += right-left+2;
}


const ll inf = 1e18;

ll a[100010];

ll findGap(int T, int N)
{
  vector<ll> v;
  if(T==1)
  {
    ll ml = 1; ll mr = N; a[0] = -1; a[N+1] = inf+1;
    while(ml <= mr)
    {
      ll mn , mx;
      MinMax(a[ml-1] + 1, a[mr+1] - 1, &a[ml], &a[mr]);
      ml++; mr--;
    }
    ll ans = 0;
    for(ll i=2;i<=N;i++) ans = max(a[i] - a[i-1] , ans);

    return ans;
  }
  else
  {
    ll s,t; MinMax(0,inf,&s,&t);
    ll delta = (t-s) / (N-1); ll ans = delta;
    ll x=s;
    for(ll i=s+1;i<=t;i+=delta)
    {
      ll mn , mx;
      MinMax(i,i+delta,&mn,&mx);
      if(mn!=-1) ans = max(ans , mn - x) , x = mx;
    }
    return ans;
  }

  return 0;
}

int main()
{
    // FILE *in = stdin, *out = stdout;
    freopen("gap.in","r",stdin);
    scanf("%d%d", &subtask_num, &N);
    for (int i=1;i<=N;i++) scanf("%lld", A+i);
    printf("%lld\n", findGap(subtask_num, N));
    printf("%lld\n", call_count);
}
*/

猜你喜欢

转载自blog.csdn.net/weixin_39708759/article/details/80261101