Loquat

loquat

from CSP-S模拟三

//虽然但是这道题式子出来了就能写出来了 
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
typedef long long ll;
ll m,x,y,u,v,w;
#define ll __int128
map<pair<ll,ll>,ll>dis[310];//记忆化,第一维是树的编号,第二维{,}是起点和终点,表示在第i棵树内a点到b点的距离 
struct tree{
	ll	siz,ans,x,u,y,v,w;//siz是树的大小,ans是路径和,x是两棵树中编号靠前那棵,u是连接x的u号点,y是两棵树中编号靠后的,v是y被连接的v点,w是uv间边权 
	tree(){
		x=y=u=v=w=siz=ans=0;
	}
}t[310];
inline ll qry(int tr,ll a,ll b){ //询问两点间距离 
	if(a==b||tr==0) return 0;  //访问到初始的树 
	if(dis[tr][{a,b}]) return dis[tr][{a,b}];
	int xx=t[tr].x,yy=t[tr].y;
//(出锅写法)	ll aa=(a<t[xx].siz?xx:yy);
//	ll bb=(b<t[xx].siz?xx:yy);
//	if(aa==xx&&bb==xx) return dis[tr][{a,b}]=dis[tr][{b,a}]=qry(xx,a,b)%mod;
//	if(aa==yy&&bb==yy) return dis[tr][{a,b}]=dis[tr][{b,a}]=qry(yy,a-t[xx].siz,b-t[xx].siz)%mod;
//	if(aa==xx&&bb==yy) return dis[tr][{a,b}]=dis[tr][{b,a}]=(qry(xx,a,t[tr].u)+qry(yy,b-t[xx].siz,t[tr].v)+t[tr].w)%mod;
//	if(aa==yy&&bb==xx) return dis[tr][{a,b}]=dis[tr][{b,a}]=(qry(xx,b,t[tr].u)+qry(yy,a-t[xx].siz,t[tr].v)+t[tr].w)%mod;
	ll aa=(a<t[xx].siz?1:0);ll bb=(b<t[xx].siz?1:0); //起点和终点分别属于哪棵子树 
	if(aa&&bb) return dis[tr][{a,b}]=dis[tr][{b,a}]=qry(xx,a,b)%mod;//同前子树,缩小范围 
	if(!aa&&!bb) return dis[tr][{a,b}]=dis[tr][{b,a}]=qry(yy,a-t[xx].siz,b-t[xx].siz)%mod;//同后子树,缩小范围,注意编号要减前树size 
	if(aa&&!bb) return dis[tr][{a,b}]=dis[tr][{b,a}]=(qry(xx,a,t[tr].u)%mod+qry(yy,b-t[xx].siz,t[tr].v)%mod+t[tr].w%mod)%mod;//一前一后,路径长度=前树点到u的距离+后树点到v的距离+uv间边权,分别递归求解 
	if(!aa&&bb) return dis[tr][{a,b}]=dis[tr][{b,a}]=(qry(yy,a-t[xx].siz,t[tr].v)%mod+qry(xx,b,t[tr].u)%mod+t[tr].w%mod)%mod;//同上 

}
map<ll,ll>di[310];//第i棵树内以j为根,所以节点到j的边权和 
inline ll qrysum(int tr,ll q){
	if(tr==0) return 0;
	if(di[tr][q]) return di[tr][q];
	int xx=t[tr].x,yy=t[tr].y;
	ll sum=0;
	if(q<t[xx].siz){//根节点在前树 ,sum=前树中以q为根的边权和+(q到u的距离+两树间边权w)*后树的大小+后树以v为根边权和 
		sum=((qry(xx,q,t[tr].u)+t[tr].w)%mod*t[yy].siz%mod)%mod;
		sum=(sum+qrysum(yy,t[tr].v)+qrysum(xx,q))%mod;
	}
	else{//根节点在后树 ,同上 
		sum=((qry(yy,q-t[xx].siz,t[tr].v)+t[tr].w)%mod*t[xx].siz%mod);
		sum=(sum+qrysum(xx,t[tr].u)+qrysum(yy,q-t[xx].siz))%mod;
	}

	di[tr][q]=sum;
	return sum;
}
int main(){
	freopen("loquat.in","r",stdin);
	freopen("loquat.out","w",stdout);
	std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>m;
	t[0].siz=1;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>u>>v>>w;
		t[i].siz=t[x].siz+t[y].siz;t[i].x=x;t[i].y=y;
		t[i].u=u;t[i].v=v;t[i].w=w;
		t[i].ans=(1ll*t[x].siz*qrysum(y,v)%mod+1ll*qrysum(x,u)*t[y].siz%mod+1ll*t[x].siz*t[y].siz%mod*w%mod+1ll*t[x].ans+1ll*t[y].ans)%mod;
		cout<<(long long)t[i].ans<<'\n';
	}
	return 0;
}

posted @ 2025-08-09 15:40  _dlwlrma  阅读(9)  评论(0)    收藏  举报