[FJOI2015] 世界树 题解
咱们看到了数据范围之后,不要畏惧,因为这说明正解是一个结论,推出结论再套一个高精咱们就胜利啦!!!
首先可以判断需要贪心,就是说我们要尽可能保证多的点,满足其左右子树的最大深度相差
从大局观入手,我们现在得到树根
由此就可以想到,设
初始化:
那么我们就可以得到
接着我们就可以尝试拓展到其它
因此我们求出
由于
「????」
我们发现这样做,预处理需要的空间太大了,然而最终查询用到的只有
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=55;
namespace BigInterger{//找同学要的压位高精度板子
struct Int{
int sign;
std::vector<int>v;
inline Int():sign(1){}
inline Int(const std::string&s){*this=s;}
inline Int(const int&v){
char buf[21];
sprintf(buf,"%d",v);
*this=buf;
}
inline void zip(const int&unzip){
if(!unzip)
for(int i=0;i<v.size();++i)
v[i]=get_pos(i<<2)+ get_pos(i<<2|1)*10+get_pos(i<<2|2)*100+get_pos(i<<2|3)*1000;
else
for(int i=(v.resize(v.size()<<2),v.size()-1),a;~i;--i)
a=((i&3)>=2)?v[i>>2]/100:v[i>>2]%100,v[i]=(i&1)?a/10:a%10;
setsign(1,1);
}
inline int get_pos(const int&pos)const{return pos>=v.size()?0:v[pos];}
inline Int&setsign(const int&newsign,const int&rev){
while(v.size()>1&&!v.back())v.pop_back();
sign=(v.empty()||(v.size()==1&&!v[0]))?1:(rev?newsign*sign:newsign);
return *this;
}
inline std::string to_str()const{
Int b=*this;
std::string s;
for(int i=(b.zip(1),0);i<b.v.size();++i)
s+=(char)(*(b.v.rbegin()+i)^48);
return (sign<0?"-":"")+(s.empty()?"0":s);
}
inline bool absless(const Int&b)const{
if(v.size()!=b.v.size())return v.size()<b.v.size();
for(int i=v.size()-1;~i;--i)
if(v[i]!=b.v[i])return v[i]<b.v[i];
return false;
}
inline Int operator-()const{
Int c=*this;
c.sign=(v.size()>1||v[0])?-c.sign:1;
return c;
}
inline Int&operator=(const std::string&s){
if(s[0]=='-')
*this=s.substr(1);
else{
for(int i=(v.clear(),0);i<s.size();++i)
v.push_back(*(s.rbegin()+i)^48);
zip(0);
}
return setsign(s[0]=='-'?-1:1,sign=1);
}
inline bool operator<(const Int&b)const{
return sign!=b.sign?sign<b.sign:(sign==1?absless(b):b.absless(*this));
}
inline bool operator==(const Int&b)const{return v==b.v&&sign==b.sign;}
inline Int&operator+=(const Int&b){
if(sign!=b.sign)return *this=(*this)-(-b);
v.resize(std::max(v.size(),b.v.size())+1);
for(int i=0,carry=0;i<b.v.size()||carry;++i){
carry+=v[i]+b.get_pos(i);
v[i]=carry%10000,carry/=10000;
}
return setsign(sign,0);
}
inline Int operator+(const Int&b)const{
Int c=*this;
return c+=b;
}
inline Int operator++(){return *this+=1;}
inline Int operator-(const Int&b)const{
if(b.v.empty()||b.v.size()==1&&!b.v[0])return *this;
if(sign!=b.sign)return (*this)+(-b);
if(absless(b))return -(b-*this);
Int c;
for(int i=0,borrow=0;i<v.size();++i){
borrow+=v[i]-b.get_pos(i);
c.v.push_back(borrow);
c.v.back()-=10000*(borrow>>=31);
}
return c.setsign(sign,0);
}
inline Int operator-=(const Int&b){return *this=*this-b;}
inline Int operator--(){return *this-=1;}
inline void add_mul(const Int&b,int mul){
v.resize(std::max(v.size(),b.v.size())+2);
for(int i=0,carry=0;i<b.v.size()||carry;++i){
carry+=v[i]+b.get_pos(i)*mul;
v[i]=carry%10000,carry/=10000;
}
}
inline Int operator*(const Int&b)const{
if(b<*this)return b*(*this);
Int c,d=b;
for(int i=0;i<v.size();++i,d.v.insert(d.v.begin(),0))
c.add_mul(d,v[i]);
return c.setsign(sign*b.sign,0);
}
inline Int operator*=(const Int&b){return *this=*this*b;}
inline Int operator/(const Int&b)const{
if(b.v.size()==1&&!b.v[0]){
std::cout<<"Divisor is 0.\nCheck your code now.\n";
exit(0);
return 0x7fffffff;
}
Int c,d;
d.v.resize(v.size());
double db=1.0/(b.v.back()+(b.get_pos((unsigned)b.v.size()-2)/1e4)+(b.get_pos((unsigned)b.v.size()-3)+1)/1e8);
for(int i=v.size()-1;~i;--i){
c.v.insert(c.v.begin(),v[i]);
int m=(c.get_pos(b.v.size())*10000+c.get_pos((int)b.v.size()-1))*db;
c-=b*m,c.setsign(c.sign,0),d.v[i]+=m;
while(c>=b)c-=b,++d.v[i];
}
return d.setsign(sign*b.sign,0);
}
inline Int operator/=(const Int&b){return *this=*this/b;}
inline Int operator%(const Int&b)const{return *this-*this/b*b;}
inline Int operator%=(const Int&b){return *this=*this%b;}
inline bool operator>(const Int&b)const{return b<*this;}
inline bool operator<=(const Int&b)const{return !(b<*this);}
inline bool operator>=(const Int&b)const{return !(*this<b);}
inline bool operator!=(const Int&b)const{return !(*this==b);}
};
inline std::istream& operator>>(std::istream& stream,Int&x){
std::string str;
stream>>str;
x=str;
return stream;
}
inline std::ostream& operator<<(std::ostream& stream,const Int&x){
stream<<x.to_str();
return stream;
}
}using BigInterger::Int;
struct node
{
Int x;
int id;
bool operator<(const node &f)const{ return x<f.x; }
}q[MAXN];
int res[MAXN];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T;
cin>>T;
for(int i=1;i<=T;i++) cin>>q[i].x,q[i].id=i;
sort(q+1,q+T+1);//大力离线
Int A=1,B=2,C;//滚动需要的变量
int j=1;
for(int i=1;i<=T;i++)
{
while(B<=q[i].x) C=A,A=B,B=C+B+1,j++;
if(q[i].x<=2||q[i].x==6) continue;//特判
res[q[i].id]=ceil(j/2.0)-1;//统计
}
for(int i=1;i<=T;i++) cout<<res[i]<<'\n';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现