首页 > 其他分享 >UOJ #761. 【IOI2022】最罕见的昆虫

UOJ #761. 【IOI2022】最罕见的昆虫

时间:2022-09-20 18:44:56浏览次数:95  
标签:int 761 mid IOI2022 using UOJ Fl Id define

题面传送门

首先有一个显然的想法:从小到大枚举答案,每次尝试将每个数加进去,如果加进去大小能在枚举的这个答案以内那就加进去,否则就不加。容易发现这是\(O(n^2)\)的询问次数,能过10pts

我们发现这个枚举答案的过程实际上是有单调性的,因此可以二分,每次仍然扫一遍,询问次数\(O(n\log n)\)似乎能过50pts。

这里我们将每次的二分过程独立开来,肯定没有办法挖掘到一些有用的信息。因此我们考虑缩小范围。

首先可以先用\(n\)次询问问出有几种数,记为\(C\),显然答案不会超过\(\frac{n}{C}\)。

则当前答案所处区间为\([1,\frac{n}{C}]\),取中点\(mid\),看mid能否取到。

若\(mid\)可以取到,那么当前\(mid\times C\)个数是没有用的,因为在更高的答案中依然可以取到,因此下一层可以少掉一半的询问次数。

若\(mid\)不能取到,则剩下\(n-mid\times C\)个数也是没有用的因为答案更小,所以不会被取到。

可以发现每次询问次数会减半,则询问次数为\(3n\)级别的。然后你会获得99pts的好成绩。

这个看上去其实\(3n\)次询问很对,为什么会错呢?

实际上如果当前二分区间答案为奇数,则会造成两边划分不均的情况,也就是说在最坏情况下会做到\(3n+C\log n\)的复杂度,因此当这种情况的时候我们随机划分,期望就是\(3n\)次询问的,多交几遍就好了。脸黑的作者交了5遍才过/kx

code:

#include "insects.h"
#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=2e3+5,M=(1<<20)+5,K=1e5+5,mod=998244353,Mod=mod-1;const db eps=1e-5;mt19937 rnd(time(0));
int n,Si,Fl[N];vector<int> Id;
int Solve(int l,int r,vector<int> Id){
	if(l==r) return l;vector<int> P;P.clear();int m=l+r>>1,Ct=0;if(R(2)^1&&(r-l+1)&1&&Si*(r-l)==Id.size()) m--; 
	for(int i:Id) if(Ct!=(m-l+1)*Si) move_inside(i),press_button()>m-l+1?(move_outside(i),0):(Ct++,Fl[i]=1);
	if(Ct==Si*(m-l+1)) {for(int i:Id) !Fl[i]&&(P.PB(i),0),Fl[i]&&(move_outside(i),0);Me(Fl,0);return Solve(m+1,r,P);}
	for(int i:Id) Fl[i]&&(P.PB(i),move_outside(i),0);Me(Fl,0);return Solve(l,m,P);
}
int min_cardinality(int Ns) {
	int i;n=Ns;for(i=0;i<n;i++) move_inside(i),press_button()>1?(move_outside(i),0):(Si++,Fl[i]=1);cerr<<Si<<'\n';
	for(i=0;i<n;i++) !Fl[i]?Id.PB(i):move_outside(i);Me(Fl,0);if(Si==n) return 1;return Solve(1,Ns/Si,Id);
}

标签:int,761,mid,IOI2022,using,UOJ,Fl,Id,define
From: https://www.cnblogs.com/275307894a/p/16712114.html

相关文章

  • IOI2022乱做
    最罕见的昆虫考虑二分答案。首先花\(n\)次算出种类。记有\(n\)只昆虫,\(c\)个种类的最小步数为\(F(n,c)\)。枚举一个答案\(ans\),接下来\(O(n)\)check它:往机器......
  • IOI2022
    鲶鱼塘\((\texttt{Easy}\0/3)\)设第\(i\)列的高度为\(h_i\),若\(h_{i-1}>h_i<h_{i+1}\),则可以直接令\(h_i=0\)。于是可以设\(f_{i,j}\)表示\(h_{......
  • UOJ #515. 【UR #19】前进四
    题面传送门UOJ是真的引领时代潮流。首先显然有一个线段树维护区间单调栈的方法,但是是\(O(m\log^2n)\)的并不够优秀。因为我们不需要知道区间的信息,我们只需要知道后缀的......
  • IOI2022 数字电路
    第一次体验当年IOI的题(虽然是Day2的签到)这题有一个经典的套路——在一些计数DP题,我们不直接统计方案数,而是统计出现合法方案的概率。这样我们设\(dp(i)\)表示子树\(i\)内......
  • [uoj749]稳健型选手
    关于后手的策略,等价于限制先手在前$2i$个数中至多选$i$个当$|[l,r]|$为奇数时,先手必然取走$a_{r}$,并以此转换为$[l,r)$的问题在此基础上,对$l$的奇偶性分类讨论,并以此将相......
  • 【笔记】IOI2022
    「IOI2022」鲶⻥塘签到题。如果我们记\(a_i\)表示第\(i\)列的高度,那么一定不存在\(a_i\gea_{i+1}\lea_{i+2}(a_{i+1}\neq0)\)的情况,假设存在,我们将\(a_{i+......
  • UOJ #217 -【UNR #1】奇怪的线段树(路径覆盖+简单优化建图)
    UOJ题面传送门orz卷王aaabcd/bx随便开了道aaabcd卷过的题然后完全想偏了,想成奇怪的DP了(果然aaabcd全方位六边形我啊)首先,如果一个点是白的但它子树内有黑点,那......