赛后题解
利用斐波拉契数列相减找到位移量再线段树维护区间最小值,秀的飞起。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc (o<<1)
#define rc (o<<1|1)
const int N=5e6+10,T=1e6+10,K=1e4+10;
int t,prime[K*40],p,fib[50],g[K],ans[K],mn[K<<5],lazy[K<<5],pos[K<<5],Id[K<<5],res[T];
bool iscomp[N];
short cnt[N];
struct node{
int n,k,id;
bool operator <(const node&rhs)const{
return n<rhs.n;}
}ask[T];
void primetable()
{
for(int i=2;i<N;i++)
{
if(!iscomp[i])prime[p++]=i,cnt[i]=1;
for(int j=0;j<p&&i*prime[j]<N;j++)
{
iscomp[i*prime[j]]=1;cnt[i*prime[j]]=cnt[i]+1;
if(i%prime[j]==0)break;
}
}
}
void build(int o,int l,int r)
{
mn[o]=1;
if(l==r)
{
Id[o]=l;pos[o]=o;
return;
}
int mid=l+r>>1;
build(lc,l,mid);build(rc,mid+1,r);
pos[o]=pos[lc];
}
void push_down(int o,int l,int r)
{
if(!lazy[o])return;
int mid=l+r>>1;
lazy[lc]+=lazy[o];lazy[rc]+=lazy[o];
mn[lc]+=lazy[o];mn[rc]+=lazy[o];
lazy[o]=0;
}
void update(int o,int l,int r,int nl,int nr,int v)
{
if(nl<=l&&r<=nr)
{
mn[o]+=v;lazy[o]+=v;
return;
}
push_down(o,l,r);
int mid=l+r>>1;
if(nl<=mid)update(lc,l,mid,nl,nr,v);
if(nr>mid)update(rc,mid+1,r,nl,nr,v);
mn[o]=min(mn[lc],mn[rc]);
pos[o]=(mn[o]==mn[lc]?pos[lc]:pos[rc]);
}
int main()
{
//freopen("in.txt","r",stdin);
primetable();fib[0]=1,fib[1]=1;
for(int i=2;i<50;i++)fib[i]=fib[i-1]+fib[i-2];
for(int i=49;i>1;i--)fib[i]-=fib[i-1];
for(int i=1;i<=10000;i++)g[i]=1;
scanf("%d",&t);
for(int i=1;i<=t;i++)
scanf("%d%d",&ask[i].n,&ask[i].k),ask[i].id=i;
sort(ask+1,ask+t+1);int m=ask[t].n;
memset(ans,-1,sizeof(ans));
build(1,1,10000);
for(int i=1,mi,add,ID,id=1;id<=t&&i<=m;i++)
{
mi=pos[1],ID=Id[mi];
update(1,1,10000,ID,ID,0);
add=mn[mi];
update(1,1,10000,1,ID,-add);
if(add>1&&ID<10000)
update(1,1,10000,ID+1,10000,1-add);
update(1,1,10000,ID,ID,fib[++g[ID]]);
while(id<=t&&ask[id].n<i+add-1)res[ask[id].id]=ans[ask[id].k],id++;
i+=add-1;if(id>t||i>m)break;
ans[ID]+=cnt[i]+(ans[ID]<0);
while(id<=t&&ask[id].n<=i)res[ask[id].id]=ans[ask[id].k],id++;
}
for(int i=1;i<=t;i++)printf("%d\n",res[i]);
return 0;
}
总结
二麻二麻。斐波拉契数列相减那段挺好,还有那个最小值大于1的trick