#分治#JZOJ 4211 送你一颗圣诞树

题目

有\(m+1\)棵树分别为\(T_{0\sim m}\),一开始只有\(T_0\)有一个点,编号为0。
对于每棵树\(T_i\)由T_{a_i}\(的第\)c_i\(个点与\)T_{b_i}\(的第\)d_i\(个点连接后形成。 其中边\)(c_i,d_i)\(的权值为\)l_i\(,若\)T_{a_i}\(有\)s\(个节点,那么原\)T_{b_i}\(部分的编号都要加上\)s$

未完待续

代码

#include <cstdio>
#include <cctype>
#include <map>
#define rr register
using namespace std;
typedef long long lll; const int mod=1000000007;
struct rec{int a,b; lll x,y; int w; lll siz;}tre[61];
map<pair<lll,lll>,int>uk[61]; int n,ans[61];
inline lll iut(){
	rr lll ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline signed Get(int k,lll x,lll y){
	if (x>y) x^=y,y^=x,x^=y;
	if (!k||x==y) return 0;
	rr lll A=tre[k].a,B=tre[k].b,sizA=tre[A].siz,sizB=tre[B].siz;
    if (y<sizA) return Get(A,x,y);
        else if (x>=sizA&&y>=sizA) return Get(B,x-sizA,y-sizA);
            else {
            	rr pair<lll,lll>t=make_pair(x,y);
            	if (uk[k].find(t)!=uk[k].end()) return uk[k][t];
            	return uk[k][t]=mo(mo(Get(A,tre[k].x,x),Get(B,tre[k].y,y-sizA)),tre[k].w);
			}
}
inline signed calc(int k,lll x){
	rr pair<lll,lll>t=make_pair(x,0); if (!k) return 0;
	if (uk[k].find(t)!=uk[k].end()) return uk[k][t];
	rr int &ans=uk[k][t]; ans=0;
	rr lll A=tre[k].a,B=tre[k].b,sizA=tre[A].siz,sizB=tre[B].siz,moA=sizA%mod,moB=sizB%mod;
	if (x<sizA) ans=mo(mo(calc(tre[k].a,x),calc(tre[k].b,tre[k].y)),mo(tre[k].w,Get(tre[k].a,tre[k].x,x))*moB%mod);
	    else ans=mo(mo(calc(tre[k].a,tre[k].x),calc(tre[k].b,x-sizA)),mo(tre[k].w,Get(tre[k].b,tre[k].y,x-sizA))*moA%mod);
	return ans;
} 
signed main(){
	for (rr int Test=iut();Test;--Test){
		n=iut(),tre[0].siz=1,ans[0]=0;
		for (rr int i=1;i<=n;++i)
		    tre[i]=(rec){iut(),iut(),iut(),iut(),iut(),0},
		        tre[i].siz=tre[tre[i].a].siz+tre[tre[i].b].siz;
		for (rr int i=0;i<=n;++i) uk[i].clear();
		for (rr int i=1;i<=n;++i){
			rr lll A=tre[i].a,B=tre[i].b,sizA=tre[A].siz,sizB=tre[B].siz,moA=sizA%mod,moB=sizB%mod;
			rr int t1=moA*calc(tre[i].b,tre[i].y)%mod,t2=calc(tre[i].a,tre[i].x)*moB%mod;
			ans[i]=mo(mo(mo(ans[A],ans[B]),tre[i].w*moA%mod*moB%mod),mo(t1,t2));
		}
		for (rr int i=1;i<=n;++i) print(ans[i]),putchar(10);
	}
	return 0;
} 
上一篇:【JZOJ】1005:【入门】输入一个三位数,把个位和百位对调后输出


下一篇:jzoj 6797. 【2014广州市选day2】hanoi