zoukankan      html  css  js  c++  java
  • JZOJ 4211. 【五校联考1day2】送你一颗圣诞树(分治)

    JZOJ 4211. 【五校联考1day2】送你一颗圣诞树

    题目

    Description

    再过三个多月就是圣诞节了,小R想送小Y一棵圣诞树作为节日礼物。因为他想让这棵圣诞树越大越好,所以当然是买不到能够让他满意的树的,因此他打算自己把这棵树拼出来。

    现在,小R开始画这棵树的设计图纸了。因为这棵树实在太大,所以他采用了一种比较方便的方法。首先他定义了 m + 1 m+ 1 m+1棵树 T 0 T0 T0 T m Tm Tm。最开始他只画好了 T 0 T0 T0 的图纸:就只有一个点,编号为0。

    接着,对于每一棵树 T i Ti Ti,他在 T a i Tai Tai的第 c i ci ci个点和 T b i Tbi Tbi的第 d i di di个点之间连上了一条长度为 l i li li的边。在 T i Ti Ti中,他保持 T a i Tai Tai中的所有节点编号不变,然后如果 T a i Tai Tai中有 s s s个节点,他会把 T b i Tbi Tbi中的所有节点的编号加上 s s s

    终于,他画好了所有的树。现在他定义一颗大小为n 的树的美观度为在这里插入图片描述其中 d ( i , j ) d(i,j) d(i,j) 为这棵树中i 到j 的最短距离。

    为了方便小R选择等究竟拼哪一棵树,你可以分别告诉他 T 1 T1 T1 T m Tm Tm的美观度吗?答案可能很大,请对 1 0 9 + 7 10^9 + 7 109+7取模后输出。

    Input

    第一行输入一个正整数 T T T 表示数据组数。每组数据的第一行是一个整数 m m m,接下来 m m m行每行五个整 a i , b i , c i , d i , l i ai, bi, ci, di, li ai,bi,ci,di,li,保证 0 ≤ a i , b i < i 0≤ai, bi < i 0ai,bi<i 0 ≤ l i ≤ 1 0 9 0≤li≤10^9 0li109 c i , d i ci, di ci,di存在。

    Output

    对于每组询问输出 m m m行。第 i i i行输出 T i Ti Ti的权值

    Sample Input

    1
    2
    0 0 0 0 2
    1 1 0 0 4

    Sample Output

    2
    28

    Data Constraint

    对于30%的数据, m ≤ 8 m≤8 m8
    对于60% 的数据, m ≤ 16 m≤16 m16
    对于100% 的数据, 1 ≤ m ≤ 60 1≤m≤60 1m60 T ≤ 100 T≤100 T100

    题解

    • 点数到最后可能会有 2 60 2^{60} 260个,会很大,不可能每个都存下来。

    • 只考虑怎么计算要求的答案就好。

    • 对于每一棵(题目写的是“颗”)树 i i i,记录 e [ i ] . a , e [ i ] . b , e [ i ] . c , e [ i ] . d , e [ i ] . l e[i].a,e[i].b,e[i].c,e[i].d,e[i].l e[i].ae[i].be[i].ce[i].de[i].l如题目中的 a , b , c , d , l a,b,c,d,l abcdl,记录 e [ i ] . s e[i].s e[i].s表示树的大小。为了方便计算,把节点编号统一 + 1 +1 +1

    • 易得 e [ i ] . s = e [ e [ i ] . a ] . s + e [ e [ i ] . b ] . s e[i].s=e[e[i].a].s+e[e[i].b].s e[i].s=e[e[i].a].s+e[e[i].b].s.

    • 定义函数 a l l ( T , x ) all(T,x) all(T,x)表示 T T T树上所有节点到 x x x节点的距离和(其中 x x x是在 T T T树中的编号)。

    • 定义函数 t o ( T , x , y ) to(T,x,y) to(T,x,y)表示 T T T树上节点 x x x到节点 y y y的距离(其中 x , y x,y x,y都是 T T T树中的编号)。

    • 发现只有这两个函数,就可以计算出答案,而且这两个函数可以通过自己不断类似分治地求答案。

    • 部分式子如下:

    • 先令 a = e [ i ] . a , b = e [ i ] . b , c = e [ i ] . c , d = e [ i ] . d a=e[i].a,b=e[i].b,c=e[i].c,d=e[i].d a=e[i].ab=e[i].bc=e[i].cd=e[i].d

    • 那么 a n s [ i ] = a n s [ a ] ∗ a n s [ b ] + e [ a ] . s ∗ e [ b ] . s ∗ e [ i ] . l + e [ a ] . s ∗ a l l ( b , d ) + e [ b ] . s ∗ a l l ( a , c ) ans[i]=ans[a]*ans[b]+e[a].s*e[b].s*e[i].l+e[a].s*all(b,d)+e[b].s*all(a,c) ans[i]=ans[a]ans[b]+e[a].se[b].se[i].l+e[a].sall(b,d)+e[b].sall(a,c).

    • a l l ( T , x ) all(T,x) all(T,x)

    • 1、如果 e [ T ] . s = 1 e[T].s=1 e[T].s=1,返回值为 0 0 0

    • 2、如果 x x x在左子树上,返回值为 a l l ( a , x ) + a l l ( b , d ) + e [ b ] . s ∗ ( e [ T ] . l + t o ( a , x , c ) ) all(a,x)+all(b,d)+e[b].s*(e[T].l+to(a,x,c)) all(a,x)+all(b,d)+e[b].s(e[T].l+to(a,x,c))

    • 3、如果 x x x在右子树上,返回值为 a l l ( b , x − e [ a ] . s ) + a l l ( a , c ) + e [ a ] . s ∗ ( e [ T ] . l + t o ( b , x − e [ a ] . s , d ) ) all(b,x-e[a].s)+all(a,c)+e[a].s*(e[T].l+to(b,x-e[a].s,d)) all(b,xe[a].s)+all(a,c)+e[a].s(e[T].l+to(b,xe[a].s,d))。( x − e [ a ] . s x-e[a].s xe[a].s是转化为右子树中的编号)

    • t o ( T , x , y ) to(T,x,y) to(T,x,y):保证 x ≤ y x≤y xy

    • 1、如果 x = y x=y x=y,返回值为 0 0 0

    • 2、如果 x , y x,y x,y都在左子树上,返回值为 t o ( a , x , y ) to(a,x,y) to(a,x,y)

    • 3、如果 x , y x,y x,y都在右子树上,返回值为 t o ( b , x , y ) to(b,x,y) to(b,x,y)

    • 4、如果 x x x在左子树上, y y y在右子树上,返回值为 t o ( a , x , c ) + e [ T ] . l + t o ( b , y − e [ a ] . s , d ) to(a,x,c)+e[T].l+to(b,y-e[a].s,d) to(a,x,c)+e[T].l+to(b,ye[a].s,d)。( y − e [ a ] . s y-e[a].s ye[a].s是转化为右子树中的编号)

    • 这样就能解决 60 60 60分了。

    • 因为有很多重复计算的,所以考虑记忆化,

    • 但是函数带的参数过大,需要用哈希表来存储。

    • 对于 a l l all all函数,存入 t ∗ x t*x tx

    • 对于 t o to to函数,存入 t ∗ x ∗ y t*x*y txy

    • 模数取 2 ∗ 1 0 5 + 9 2*10^5+9 2105+9,哈希表大小 5 ∗ 1 0 5 5*10^5 5105即可。

    • 记得每次计算都要模数,否则会出现负数,而且错误总是难以查出。

    代码

    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define LL long long 
    #define md 1000000007
    #define z 200009
    LL m,tn;
    struct node
    {
    	LL s,l,a,b,c,d;
    }e[61];
    LL ans[61];
    struct
    {
    	LL u,v,s,t,id;
    }hx[500010],hs[500010];
    LL hash(LL t,LL v)
    {
    	LL x=(t%z)*(v%z)%z;
    	while(hs[x].id==tn+1)
    	{
    		if(hs[x].t==t&&hs[x].v==v) return x;
    		x++;		
    		if(x>500000) x=1;
    	}
    	return -x;
    }
    LL haxi(LL t,LL u,LL v)
    {
    	LL x=(t%z)*(u%z)%z*(v%z)%z;
    	while(hx[x].id==tn+1)	
    	{
    		if(hx[x].t==t&&hx[x].u==u&&hx[x].v==v) return x;
    		x++;
    		if(x>500000) x=1;
    	}
    	return -x;
    }
    LL to(LL t,LL u,LL v)
    {
    	LL ss=e[e[t].a].s,sum;
    	LL hs1=haxi(t,u,v);
    	if(hs1>0) return hx[hs1].s; 
    	if(u>v) 
    	{
    		LL tp=u;u=v,v=tp;
    	}
    	if(u==v) return 0;
    	if(v<=ss) sum=to(e[t].a,u,v);
    	else if(u>ss) sum=to(e[t].b,u-ss,v-ss);
    	else sum=(to(e[t].a,u,e[t].c)+to(e[t].b,v-ss,e[t].d)+e[t].l)%md;
    	hx[-hs1].t=t;
    	hx[-hs1].s=sum%md;
    	hx[-hs1].u=u;
    	hx[-hs1].v=v;
    	hx[-hs1].id=tn+1;
    	return sum;
    }
    LL all(LL t,LL v)
    {
    	LL ss=e[e[t].a].s,sum;
    	LL hs1=hash(t,v);
    	if(hs1>0) return hs[hs1].s;
    	if(e[t].s==1) return 0;
    	if(v<=ss) sum=(all(e[t].a,v)+all(e[t].b,e[t].d)+e[e[t].b].s%md*e[t].l%md+e[e[t].b].s%md*to(e[t].a,v,e[t].c)%md)%md;
    	else sum=(all(e[t].b,v-ss)+all(e[t].a,e[t].c)+e[e[t].a].s%md*e[t].l%md+e[e[t].a].s%md*to(e[t].b,v-ss,e[t].d)%md)%md;
    	hs[-hs1].t=t;
    	hs[-hs1].s=sum%md;
    	hs[-hs1].v=v;
    	hs[-hs1].id=tn+1;
    	return sum;
    }
    int main()
    {
    	scanf("%lld",&tn);
    	while(tn--)
    	{
    		scanf("%lld",&m);
    		e[0].s=1;
    		LL a,b,c,d;
    		for(LL i=1;i<=m;i++)
    		{
    			scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&e[i].l);
    			c++,d++;
    			e[i].a=a,e[i].b=b,e[i].c=c,e[i].d=d;
    			e[i].s=e[a].s+e[b].s;
    			ans[i]=ans[a]+ans[b]+(e[a].s%md)*(e[b].s%md)%md*e[i].l%md+e[a].s%md*all(b,d)%md+e[b].s%md*all(a,c)%md;
    			ans[i]%=md;
    			printf("%lld
    ",ans[i]);
    		}
    	}
    	return 0;
    }
    
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    一步一步配置 Dell OME 监控 Dell 服务器硬件报警
    比较详细的介绍zabbix监控tomcat
    Docker-03 docker 加速器--DaoCloud 1.0
    Docker-02 无人值守安装 docker
    Docker-01 无人值守升级 CentOS 6.x 系统内核到 3.10.x 长期支持版
    一个awk if 嵌套 if 的脚本
    CentOS 安装 JDK
    zTree默认勾选指定ID并执行事件
    数据库游标的使用
    js进度条实现
  • 原文地址:https://www.cnblogs.com/LZA119/p/13910096.html
Copyright © 2011-2022 走看看