zoukankan      html  css  js  c++  java
  • 小奇的仓库

    题目来源:hzwer

    【题目背景】

    小奇采的矿实在太多了,它准备在喵星系建个矿石仓库。令它无语的是,喵星系的货运飞船引擎还停留在上元时代!

    【问题描述】

    喵星系有n个星球,星球以及星球间的航线形成一棵树。

    从星球a到星球b要花费[dis(a,b) Xor M]秒。(dis(a,b)表示ab间的航线长度,Xor为位运算中的异或)

    为了给仓库选址,小奇想知道,星球i(1<=i<=n)到其它所有星球花费的时间之和。

    【输入格式】

    第一行包含两个正整数n,M。
    接下来n-1行,每行3个正整数a,b,c,表示a,b之间的航线长度为c。

    【输出格式】

    n行,每行一个整数,表示星球i到其它所有星球花费的时间之和。

    【样例输入】

    4 0

    1 2 1

    1 3 2

    1 4 3

    【样例输出】

    6

    8

    10

    12

    【数据范围】

    序号 N M

    1 6 0

    2 100 5

    3 2000 9

    4 50000 0

    5 50000 0

    6 50000 1

    7 50000 6

    8 100000 10

    9 100000 13

    10 100000 15

    保证答案不超过2*10^9

     

    我们先回忆一下,如果异或值为0(就是没有异或)的情况应该怎么dp:

    假如v是u的儿子,他们之间边长为w,tot1[i]表示i子树内所有节点到i的距离和,tot2[i]表示所有非i子树内的节点到i的距离和。那么有:

    tot1[u] = sigma{ tot1[v] } + ( size[u] - 1 ) * w ( = sigma{ tot1[v] + size[v] * w } ) 

    tot2[v] = tot2[u] + ( n - size[v] ) * w ( = tot2[u] + ( n - size[u] + size[u] - size[v] ) * w ) 

    直接dfs计算。

    那么如果有异或的话,应该怎么搞呢?

    我们发现虽然n挺大、c挺大,但是异或的值M很小,最大只有15。所以这么小的异或值可以来搞些什么呢?

    我们知道对每两点间的dis,只有mod16的部分会被异或影响,那么我们用树dp求每个点到其他所有点的dis值的mod 16后1~16的各有多少个 和 >16部分(/ 16)的值.

    看下黄学长的这两段代码:

     第一段很容易懂:

    void dfs1(int x,int fa)
    {
    	for(int i=last[x];i;i=e[i].next)
    		if(e[i].to!=fa)
    		{
    			dfs1(e[i].to,x);
    			g[x]+=g[e[i].to]+e[i].v/16;
    			f[x][e[i].v%16]++;
    			for(int j=0;j<16;j++)
    			{
    				int k=j+e[i].v;
    				g[x]+=k/16*f[e[i].to][j];
    				f[x][k%16]+=f[e[i].to][j];
    			}
    		}
    }
    

     第二段需结合第一段来看:

    void dfs2(int x,int fa)
    {
    	for(int i=last[x];i;i=e[i].next)
    		if(e[i].to!=fa)
    		{
    			int tmp=g[x]-g[e[i].to];
    			for(int j=0;j<16;j++)
    			{
    				int k=j+e[i].v;
    				tmp-=k/16*f[e[i].to][j];
    				t[k%16]=f[x][k%16]-f[e[i].to][j];
    			}
    			t[e[i].v%16]--;
    			g[e[i].to]+=tmp;
    			f[e[i].to][e[i].v%16]++;
    			for(int j=0;j<16;j++)
    			{
    				int k=j+e[i].v;
    				g[e[i].to]+=k/16*t[j];
    				f[e[i].to][k%16]+=t[j];
    			}
    			dfs2(e[i].to,x);
    		}
    }
    

     

     

     

    弱者就是会被欺负呀
  • 相关阅读:
    express实现前后端通信上传图片,存储数据库(mysql)傻瓜教程(二)
    express实现前后端通信上传图片,存储数据库(mysql)傻瓜教程(一)
    [转载] 在阿里做了五年技术主管,我有话想说
    阿里云RDS MySql还原到本地Linux/Centos
    如何领域驱动设计?-实践感悟&总结分享
    jira + confluence 安装和破解
    RabbitMQ安装和配置
    [转]技术路线的选择重要但不具有决定性
    .Net core2.0日志组件Log4net、Nlog简单性能测试
    在微服务中使用领域事件
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7580858.html
Copyright © 2011-2022 走看看