• 代码风格与树形DP


    Streaming很惨,不过因为比赛之间没有提交过就没掉(或掉了)rating.第二题是一个树形DP,但是我都在想第一题了,简直作死.

    看着神犇的代码我也是醉了...各种宏,真是好好写会死系列. 看到他们Tree DP都用的DFS,突然感觉我这个蒟蒻的生活中充满了无力...

    我一般都喜欢用BFS进行Tree DP.这样坏处很多,难调试,容易爆空间等.好处也有,写起来快,代码短,跑得飞快,判重简单.不过这样做是有条件的,而今天的Streaming这题就是一道可以的题.

    然后讲讲今天这道LCAStat吧.

    作为一个不会写Tarjan LCA的蒟蒻,这道题出的比较有素质.至少你不需会LCA(树上倍增差不多会吧).有些神犇这么暴力,对此我只能表示Orz.

    让我们思考一下.对于每一个点,他的(姑且称为LCA Score)应该怎么算?

    转换个思路,如何让两个点的LCA为一个给定的点i?

    显然,这两个点必须是i或在i的不同子树中.那么我们就渐渐有了思路.

    注意算sum(x){sum(y){x*y}}有个很简单的办法即sum(x){x}*sum(y){y}

    那么求出每一棵子树的totalWeight,当在一个结点新访问到一个子结点时,这个点的对分值贡献就是totw[i]*(noww[d]+w[d])*2

    totw[i]就是这个访问到的子结点的totalWeight,noww[d]就是已经加入这个父结点(不包括新访问的这个)的子树的总重,w[d]就是这个父结点的weight

    为什么要乘以2?因为这道题目考虑顺序,即a=3,b=5和a=5,b=3要算两次.

    每次有一个结点的所有子结点都被访问了就松弛这个结点.

    自己看代码吧,去了所有mod.

    #include <cstdio>
    #include <cstring>
    long long fat[200000],w[200000],f[200000],sub[200000],totw[200000],n,p,i,sum;
    long long q[200000],qh,qt;
    int main(int argc,char const *argv[]){
    	scanf("%lld %lld",&n,w+1);
    	for(i=2;i<=n;++i){
    		scanf("%lld %lld",fat+i,w+i);
    		++sub[fat[i]];
    	}
    	for(i=1;i<=n;++i){
    		f[i]=0;
    		if(!sub[i]){
    			q[qt++]=i;
    			totw[i]=0;
    			f[i]=0;
    		}
    	}
    	while(qh!=qt){
    		i=q[qh++];
    		f[i]+=(w[i]*w[i])*(w[i]+totw[i]*2);
    		totw[i]+=w[i];
    		sum=sum+f[i];
    		f[fat[i]]+=(totw[i]*totw[fat[i]])*w[fat[i]]*2;
    		totw[fat[i]]+=totw[i];
    		--sub[fat[i]];
    		if(!sub[fat[i]]) q[qt++]=fat[i];
    	}
    	printf("%lld
    ", sum);
    	return 0;
    }
    //非AC代码,只是为了清楚的一份演示代码
    

      

  • 相关阅读:
    tcp/ip 调优示例
    【ASP.NET】IHttpHandler和IHttpModule
    【.NET框架】Dapper ORM 用法—Net下无敌的ORM
    【JavaScript】setinterval和setTimeout的区别
    【javascript】基于javascript的小时钟
    【ASP.NET】必须知道的ASP.NET核心处理
    【ASP.NET MVC】 路由机制:命名路由
    【ASP.NET MVC】提高页面加载速度:脚本优化
    SMTP协议--在cmd下利用命令行发送邮件
    【ASP.NET MVC】HTML5+MVC上传文件显示进度
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4006534.html
Copyright © 2020-2023  润新知