peiwenjun's blog 没有知识的荒原

LOJ3834 「IOI2022」最罕见的昆虫

题目描述

这是一道交互题。

交互库有一个长为 \(n\) 的数组 \(a\)

你需要实现以下函数:

  • int min_cardinality(int N)

    返回数组 \(a\) 中出现次数最少的数的出现次数。

你可以调用以下函数:

  • void move_inside(int i)

    \(a_i\) 加入可重集 \(S\)

  • void move_outside(int i)

    \(a_i\)\(S\) 中删除,如果 \(a_i\) 不在 \(S\) 中则不执行任何操作。

  • int press_button()

    询问 \(S\)出现次数最多的数出现次数。

每个函数最多可以调用 \(3n\) 次。

数据范围

  • \(1\le n\le 2000\)

时间限制 \(\texttt{2s}\) ,空间限制 \(\texttt{2048MB}\)

分析

保持集合中每个数最多出现 \(1\) 次,可以用 \(n\) 次操作得到不同颜色种类数,记为 \(k\)

二分答案,保持集合中每个数最多出现 \(x\) 次,那么判断答案 \(\ge x\) 等价于判断集合大小是否等于 \(kx\)

于是我们得到了一个操作次数 \(\mathcal O(n\log n)\) 的做法。

考虑优化。

  • 如果答案 \(<x\) ,那么每种颜色保留 \(x\) 个已经足够,无需需要考虑集合外的数。
  • 如果答案 \(\ge x\) ,那么后面二分时不再操作集合内的 \(kx\) 个数。

再来分析一下操作次数。

假设我们已经二分到区间 \([l,r]\) ,那么只需要考虑不超过 \((r-l+1)\cdot k\) 个数。

由于每次二分值域减半,因此操作次数 \(\approx n+(n+\frac n2+\frac n4+\cdots)\approx 3n\)

直接交可以获得 \(99pts\) 的成绩,原因是每次二分时,如果 \(l,r\) 奇偶性不同,我们无法恰好取在区间中点。

加上一点随机扰动,每次取 mid=(l+r+(rnd()&1))/2 即可,时间复杂度\(O(n\log n)\)

有可能需要一个好一点的随机种子。

#include<bits/stdc++.h>
#include"insects.h"
#define add move_inside
#define del move_outside
#define query press_button
using namespace std;
const int maxn=2005;
int k,n;
bool has[maxn],vis[maxn];
mt19937 rnd(998244353);
bool check(int x)
{
    for(int i=0;i<n;i++)
    {
        if(vis[i]) continue;
        add(i);
        if(query()<=x) has[i]=true;
        else del(i);
    }
    int cnt=0;
    for(int i=0;i<n;i++) cnt+=has[i];
    if(cnt==k*x)
    {
        for(int i=0;i<n;i++) vis[i]|=has[i];
        return true;
    }
    else
    {
        for(int i=0;i<n;i++)
            if(!vis[i]&&has[i]) has[i]=false,del(i);
            else vis[i]=true;
        return false;
    }
}
int min_cardinality(int _n)
{
    n=_n;
    for(int i=0;i<n;i++)
    {
        add(i);
        if(query()==1) has[i]=vis[i]=true,k++;
        else del(i);
    }
    int l=1,r=n/k+1;
    while(r-l>1)
    {
        int mid=(l+r+(rnd()&1))/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    return l;
}

posted on 2023-01-20 21:30  peiwenjun  阅读(15)  评论(0)    收藏  举报

导航