hdu 5401 Persistent Link/cut Tree

题意:每次合并两棵树,求新树两两顶点间距之和
解法:记忆化搜索。将原问题划归成几个子问题,分别递归完成计数

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<string.h>
#include<set>
#include<map>
#include<queue>
#include<math.h>
#define ll long long
#define pi acos(-1)
#define PLL pair<ll,ll>
#define PLLL pair<PLL,ll>
#define MP make_pair
using namespace std;

const ll mod = 1e9+7;
const ll maxn= 1000+10;
ll m,a[maxn],b[maxn],c[maxn],d[maxn],l[maxn],ans[maxn],s[maxn],cc[maxn],dd[maxn];
map<PLLL,ll> ma;//记录三元组值的方法
ll calc(ll p,ll x,ll y){
    if(p==0) return 0;
    PLLL r=MP(MP(p,x),y);
    if(ma.find(r)!=ma.end()) return ma[r];
    if(x<s[a[p]]&&y<s[a[p]]) return ma[r]=(calc(a[p],x,y)%mod);
    else if(x<s[a[p]]&&y>=s[a[p]]) return  ma[r]=(calc(a[p],x,c[p])+calc(b[p],y-s[a[p]],d[p])+l[p])%mod;
    else if(x>=s[a[p]]&&y<s[a[p]]) return  ma[r]=(calc(a[p],y,c[p])+calc(b[p],x-s[a[p]],d[p])+l[p])%mod;
    else return  ma[r]=(calc(b[p],x-s[a[p]],y-s[a[p]])%mod);
}

ll solve(ll p,ll id){
    if(p==0) return 0;
    if(id<s[a[p]])
        return ((calc(a[p],id,c[p])+l[p])%mod*(s[b[p]]%mod)%mod+(dd[p]+solve(a[p],id))%mod)%mod;
    else{
        id=(id-s[a[p]]);
        return ((calc(b[p],id,d[p])+l[p])%mod*(s[a[p]]%mod)%mod+(cc[p]+solve(b[p],id))%mod)%mod;
    }
}

int main(){
    //freopen("a.txt","r",stdin);
    while(scanf("%lld",&m)!=EOF){
        s[0]=1; a[0]=b[0]=c[0]=d[0]=cc[0]=dd[0]=l[0]=0; ma.clear();
        for(ll i=1;i<=m;i++) s[i]=ans[i]=0;
        for(ll i=1;i<=m;i++){
            scanf("%lld%lld%lld%lld%lld",&a[i],&b[i],&c[i],&d[i],&l[i]); s[i]=s[a[i]]+s[b[i]];
            cc[i]=solve(a[i],c[i])%mod,dd[i]=solve(b[i],d[i])%mod;
            ans[i]=((cc[i]*(s[b[i]]%mod)%mod)+(dd[i]*(s[a[i]]%mod)%mod)+l[i]%mod*(s[a[i]]%mod)%mod*(s[b[i]]%mod)%mod+(ans[a[i]]+ans[b[i]])%mod)%mod;
            printf("%lld\n",ans[i]);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值