Hackerrank Fibonacci Numbers Tree

題目地址
https://www.hackerrank.com/challenges/fibonacci-numbers-tree
大意:
子樹按深度加一段連續的Fib數列
詢問兩點之間的權值和

注意到對於任意數列F
Fi=Fi1+Fi2
a>0,b>0 我們有
Fa+b=Fa1Fibb+FaFibb+1

證明可以用數學歸納法,這裏不表

然後就很輕易了 每個節點u 記錄深度然後根據深度記錄Fibdepu,Fibdepu1 之後樹剖

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章