QAQ
设小兔子编号为x
FBi<=x<=FBi+1
那么x的父亲即为
X−FBi
因为X之前有
FBi
生小兔啊
直接暴力模拟就行了
#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
ll fb[200];
int get(ll x)
{
for(int j=1;j<=61;j++)
{
if(fb[j]<=x&&x<=fb[j+1])
{
return j;
}
}
}
int main()
{
fb[1]=1ll;
for(int i=2;i<=61;i++)
{
fb[i]=fb[i-1]+fb[i-2];
/*if(fb[i]>1e12)
printf("%d\n",i);*/
}
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
ll a,b;
int tmpa,tmpb;
scanf("%lld%lld",&a,&b);
tmpa=get(a),tmpb=get(b);
while(a!=b)
{
if(a>b)
{
a-=fb[tmpa];
tmpa=get(a);
}
else
{
b-=fb[tmpb];
tmpb=get(b);
}
}
printf("%lld\n",a);
}
}
链接
如何在一个区间内查一个数字出现的次数?
疯狂脑补搞基数据结构(这个叫做数据结构病)
好像没有合适的QuQ
于是开始想正常解法。
我们可以开始想一下正常解法。
c[i][j]表示的是i颜色第j个兔子出现的位置。
不是DP
很明显c[i]里面存的兔子出现的位置是递增的。
那么我们就可以二分查找了。
查这个颜色里小于l位置的兔子有几只。
颜色里小于等于位置的兔子有几只。
然后一减就是答案了。
等一下,二维数组开多大?
开vector啊(逃~
至于修改,记录下来然后交换就行了。
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct node{
int col,w;
}a[3*110000];
vector <int> c[3*110000];
int find(int id,int x)
{
int l=1,r=c[id].size()-1;
int ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(c[id][mid]>=x) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
/*for(int i=1;i<=3*1e5;i++)
c[i].push_back(0);*/
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
c[x].push_back(i);
a[i].col=x,a[i].w=c[x].size()-1;
}
for(int i=1;i<=q;i++)
{
int opt;
scanf("%d",&opt);
if(opt==1)
{
int l,r,cr;
scanf("%d%d%d",&l,&r,&cr);
if(c[cr].size()==0)
{
printf("0\n");
continue;
}
int pos1=lower_bound(c[cr].begin(),c[cr].end(),l)-c[cr].begin();
int pos2=upper_bound(c[cr].begin(),c[cr].end(),r)-c[cr].begin();
printf("%d\n",pos2-pos1);
}
if(opt==2)
{
int x;
scanf("%d",&x);
if(a[x].col==a[x+1].col) continue;
int w1=a[x].w,w2=a[x+1].w;
int c1=a[x].col,c2=a[x+1].col;
a[x].col=c2,a[x+1].col=c1;
a[x].w=w2,a[x+1].w=w1;
c[c1][w1]=x+1;
c[c2][w2]=x;
}
}
return 0;
}