题目地址
https://www.hackerrank.com/challenges/fibonacci-numbers-tree
大意:
子树按深度加一段连续的Fib数列
询问两点之间的权值和
注意到对于任意数列
F
当
a>0,b>0
我们有
Fa+b=Fa−1∗Fibb+Fa∗Fibb+1
证明可以用数学归纳法,这里不表
然后就很轻易了 每个节点
u
记录深度然后根据深度记录
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
char c;
inline void read(int&a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
inline void read(ll&a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
const
int Base=(int)1e5+1;
const
int Mod=(int)1e9+7;
inline void AddUp(int &x)
{
if(x>=Mod)x-=Mod;
if(x<0)x+=Mod;
}
struct Matrix
{
int a[2][2];
int x,y;
void clear(){x=0,y=0;memset(a,0,sizeof(a));}
inline friend Matrix operator *(Matrix a,Matrix b)
{
Matrix c;
c.clear();
c.x=a.x,c.y=b.y;
for(int i=0;i<a.x;i++)
for(int j=0;j<b.x;j++)
for(int k=0;k<b.y;k++)
AddUp(c.a[i][k]+=a.a[i][j]*1ll*b.a[j][k]%Mod);
return c;
}
};
int res;
int &Fi(ll x)
{
x--;
res=0;
Matrix a,R,B;
B.clear();
B.x=1,B.y=2;
B.a[0][0]=1,B.a[0][1]=0;
R.clear();
R.x=R.y=2;
R.a[0][0]=R.a[1][1]=1;
a.clear();
a.x=a.y=2;
a.a[0][0]=a.a[1][0]=a.a[0][1]=1;
for(x;x;x>>=1,a=a*a)
if(x&1)R=R*a;
AddUp(res=(B.a[0][0]*1ll*R.a[0][0]+B.a[0][1]*1ll*R.a[1][0])%Mod);
return res;
}
struct A
{
int C[2*Base+1];
inline int &operator[](const ll &x)
{
if(x<=Base)
return C[x+Base];
else return Fi(x);
}
}Fib;
struct Chain{Chain*next;int u;}*Head[100001];
inline void Add(int u,int v){Chain*tp=new Chain;tp->next=Head[u];Head[u]=tp;tp->u=v;}
int Dep[Base],Siz[Base],Son[Base];
int F[Base];
int dfs(int x)
{
for(Chain*tp=Head[x];tp;tp=tp->next)
Dep[tp->u]=Dep[x]+1,Siz[x]+=dfs(tp->u),Son[x]=Siz[Son[x]]>Siz[tp->u]?Son[x]:tp->u;
return ++Siz[x];
}
int HCB[Base],HCE[Base],HCP[Base],HCN[Base];
int Hccnt;
void dfs(int x,int Bg)
{
HCB[x]=Bg;
HCN[HCP[x]=++Hccnt]=x;
if(Son[x])dfs(Son[x],Bg);
for(Chain*tp=Head[x];tp;tp=tp->next)
if(tp->u^Son[x])dfs(tp->u,Hccnt+1);
HCE[x]=Hccnt;
}
struct Node
{
int sumf1,sumf2,sumd1,sumd2,sum;
int l,r;
inline void Add(int d1,int d2)
{
AddUp(sumd1+=d1);
AddUp(sumd2+=d2);
AddUp(sum=(sum+sumf2*1ll*d2+sumf1*1ll*d1)%Mod);
}
}T[Base*6];
void Push(int place)
{
if(T[place].sumd1||T[place].sumd2){T[place<<1].Add(T[place].sumd1,T[place].sumd2),T[place<<1|1].Add(T[place].sumd1,T[place].sumd2),T[place].sumd1=0,T[place].sumd2=0;}
}
void Up(int place)
{
AddUp(T[place].sum=T[place<<1].sum+T[place<<1|1].sum);
}
void Build(int place,int l,int r)
{
T[place].l=l,T[place].r=r;
if(l^r)
Build(place<<1,l,l+r>>1),Build(place<<1|1,(l+r>>1)+1,r)
,AddUp(T[place].sumf1=T[place<<1].sumf1+T[place<<1|1].sumf1)
,AddUp(T[place].sumf2=T[place<<1].sumf2+T[place<<1|1].sumf2);
else
T[place].sumf1=Fib[Dep[HCN[l]]],
T[place].sumf2=Fib[Dep[HCN[r]]+1];
}
void Add(int place,int l,int r,int Fib1,int Fib2)
{
if(T[place].l>=l&&T[place].r<=r)return T[place].Add(Fib1,Fib2);
int mid=T[place<<1].r;
Push(place);
if(l<=mid)Add(place<<1,l,r,Fib1,Fib2);
if(mid<r)Add(place<<1|1,l,r,Fib1,Fib2);
Up(place);
}
int Query(int place,int l,int r)
{
if(T[place].l>=l&&T[place].r<=r)return T[place].sum;
int mid=T[place<<1].r,res=0;
Push(place);
if(l<=mid)AddUp(res+=Query(place<<1,l,r));
if(mid<r)AddUp(res+=Query(place<<1|1,l,r));
return res;
}
void TAdd(int u,ll del)
{
ll Fb=del-Dep[u];
int F1=Fib[Fb-1],F2=Fib[Fb];
Add(1,HCP[u],HCE[u],F1,F2);
}
int TQuery(int u,int v)
{
int res=0;
while(HCB[u]^HCB[v])
{
if(HCB[u]<HCB[v])swap(u,v);
AddUp(res+=Query(1,HCB[u],HCP[u]));
u=F[HCN[HCB[u]]];
}
AddUp(res+=Query(1,min(HCP[u],HCP[v]),max(HCP[u],HCP[v])));
return res;
}
void out(int x)
{
if(x>9)out(x/10);
putchar('0'+x%10);
}
int main()
{
int n,m;
read(n);read(m);
Fib[1]=1;
Fib[2]=1;
Dep[1]=1;
for(int i=3;i<=Base;i++)
AddUp(Fib[i]=Fib[i-2]+Fib[i-1]);
for(int i=0;i>=-Base;i--)
AddUp(Fib[i]=Fib[i+2]-Fib[i+1]);
for(int i=2;i<=n;i++)
{int f;read(f);Add(f,i);F[i]=f;}
dfs(1);dfs(1,1);Build(1,1,n);
while(m--)
{
do
c=getchar();
while(c!='U'&&c!='Q');
if(c=='U')
{
int u;ll k;
read(u),read(k);
TAdd(u,k);
}
else
{
int u,v,res;
read(u),read(v);
res=TQuery(u,v);
out(res);puts("");
}
}
Fi(3);
return 0;
}