版权声明:文章是蒟蒻写的,转载也别忘了注明出处。 https://blog.csdn.net/ganjingxian/article/details/86644203
- 很明显,如果直接弄,点数非常多
- 我们知道,一棵树的答案=两个子树的答案+size[a]*sum(b,d)+size[b]*sum(a,c)+size[a]*size[b]*l(其中sum(x,y)表示第x个树中,每个点到y的距离值和)
- 那么问题就是怎么求sum,现在我们假设y在组成x这棵树的左子树里(右子树同理),那么对于左子树这部分的贡献,我们递归求,对于右子树,我们求得右子树每个点到c的距离和(因为右子树的点想要走到y,c是必经点),加上c到y的距离*size[b]+size[b]*l
- 记dis(o,x,y)表示在第o棵树中x到y的距离,如果是分别在左子树或右子树,直接递归下去,否则转化为两个子问题+l
- 注意,size是不能模的,但是它要参与运算,所以要先模size,不然会炸,然后用map来存之前求过的东西。
- code
map是co的
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstring>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
using namespace std;
typedef long long ll;
const ll mo=1e+9+7;
struct node{
ll a,b,c,d,l,s;
};
node t[65];
typedef pair<ll,ll> note;
map <note,ll>h[65];
ll ans[65],a,b,c,d,l;
int m;
ll dis(ll o,ll x,ll y){
if (x>y) swap(x,y);
if (!o||x==y) return 0;
ll a=t[o].a,b=t[o].b,c=t[o].c,d=t[o].d,l=t[o].l;
if (y<t[a].s) return dis(a,x,y)%mo;
else if (x>=t[a].s) return dis(b,x-t[a].s,y-t[a].s)%mo;
else{
note k=make_pair(x,y);
if (h[o].find(k)!=h[o].end()) return h[o][k]%mo;
h[o][k]=((dis(a,x,c)%mo+t[o].l)%mo+dis(b,d,y-t[a].s))%mo;
return h[o][k]%mo;
}
}
ll sum(ll x,ll y){
note k=make_pair(y,0);
if (h[x].find(k)!=h[x].end()) return h[x][k];
ll a=t[x].a,b=t[x].b,c=t[x].c,d=t[x].d,l=t[x].l;
if (y<t[a].s) {
h[x][k]=(sum(a,y)+t[b].s%mo*(l+dis(a,y,c))%mo)%mo;
h[x][k]=(h[x][k]+sum(b,d))%mo;
}
else {
h[x][k]=(sum(b,y-t[a].s)+t[a].s%mo*(l+dis(b,y-t[a].s,d))%mo)%mo;
h[x][k]=(h[x][k]+sum(a,c))%mo;
}
return h[x][k];
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int T;
scanf("%d",&T);
while (T--){
memset(t,0,sizeof(t));
t[0].s=1;
memset(ans,0,sizeof(ans));
scanf("%d",&m);
fo(i,1,m){
h[i].clear();
scanf("%lld%lld%lld%lld%lld",&t[i].a,&t[i].b,&t[i].c,&t[i].d,&t[i].l);
t[i].s=t[t[i].a].s+t[t[i].b].s;
}
fo(i,1,m){
a=t[i].a; b=t[i].b; c=t[i].c; d=t[i].d; l=t[i].l;
ans[i]=(t[a].s%mo)*(t[b].s%mo)%mo*l%mo;
ans[i]=((ans[i]+ans[a])%mo+ans[b])%mo;
ans[i]=(ans[i]+t[b].s%mo*sum(a,c)%mo)%mo;
ans[i]=(ans[i]+t[a].s%mo*sum(b,d)%mo)%mo;
printf("%lld\n",ans[i]);
}
}
return 0;
}