P12464 『FCRT / 1 - 1』Seats 题解
cybermage_liu · · 题解
好像是新思路?
题意简化
每次从
思路
我们可以把找这个值看作一个在
很明显,首先
然后使用 dfs 用二分的方式搜索,类比快速幂:
设 dfs 返回值为当前长度为
如果可以选中位数,就选中位数,并以中位数为界限将原区间划分为
-
当原区间长为奇数时,
dfs(r)=dfs(r-mid)+dfs(mid) 。 -
当原区间长为偶数时,
dfs(r)=dfs(mid)\times 2 。
如果连中位数都不能选:
-
不可选第一个,原区间长为
1 ,直接返回0 。 -
可以选第一个,原区间长为
2 或3 ,直接返回1 。
这样就可以得到
#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 。
}
为什么只有
因为多次搜索到区间是奇数时,时间复杂度会大幅度退化。
不一样的地方
易发现规律
我们将原定义的返回值改成
如果其两个子区间中较小的子区间需要加
-
当区间长度为偶数时显然。
-
当区间长度为奇数时,如果给区间长度加
1 ,必然划到小区间。
不用记忆化,少开一个 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 。
}