1 条题解
-
0
自动搬运
来自洛谷,原作者为

cybermage_liu
十年星空见,一剑天地开。搬运于
2025-08-24 23:15:45,当前版本为作者最后更新于2025-05-10 13:02:16,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
好像是新思路?
题意简化
每次从 到 的范围内,找到一个最小的值,使得其与 集合内的数的最小差最大且大于 。
思路
我们可以把找这个值看作一个在 到 的区间内选数的过程。
很明显,首先 是必须要选的。
然后使用 dfs 用二分的方式搜索,类比快速幂:
设 dfs 返回值为当前长度为 ,且必须选第一个,必须不选最后一个的按题意在当前区间内选数的数的个数。
如果可以选中位数,就选中位数,并以中位数为界限将原区间划分为 个子区间。
-
当原区间长为奇数时,。
-
当原区间长为偶数时,。
如果连中位数都不能选:
-
不可选第一个,原区间长为 ,直接返回 。
-
可以选第一个,原区间长为 或 ,直接返回 。
这样就可以得到 分。
#include<bits/stdc++.h> #define int unsigned long long using namespace std; struct node{ int x,y; }; int dfs(int r){ if(r==0) return 0; if(r==1) return 0; if(r==2) return 1; if(r==3) return 1;//边界四个条件 int mid=1+r>>1;//r-mid 小于等于 mid。 if((1+r)%2==0) return dfs(mid)+dfs(r-mid);//区间长为奇 else return dfs(mid)*2;//区间长为偶 } signed main(){ int n; cin>>n; cout<<dfs(n-1)+1; //除去最后一个 n 算出来的 dfs 值需要再选上 n 。 }为什么只有 分呢?
因为多次搜索到区间是奇数时,时间复杂度会大幅度退化。
不一样的地方
易发现规律 为 或 。
我们将原定义的返回值改成 ,并新增一个 ,表示如果将当前区间长度加 , 值是否要加 。
如果其两个子区间中较小的子区间需要加 ,那么当前区间也需要加 。
-
当区间长度为偶数时显然。
-
当区间长度为奇数时,如果给区间长度加 ,必然划到小区间。
不用记忆化,少开一个 map。
时间复杂度严格 。
AC code
#include<bits/stdc++.h> #define int unsigned long long using namespace std; struct node{int x,y;}; node dfs(int r){ if(r==0) return {0,0}; if(r==1) return {0,1}; if(r==2) return {1,0}; if(r==3) return {1,1};//边界四个条件。 int mid=1+r>>1; node res=dfs(r-mid);//r-mid 小于等于 mid。 if(r%2) return {res.x*2+res.y,res.y};//区间长为奇 else return {res.x*2,res.y};//区间长为偶 } signed main(){ int n; cin>>n; cout<<dfs(n-1).x+1; //除去最后一个 n 算出来的 dfs 值需要再选上 n 。 } -
- 1
信息
- ID
- 11450
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者