小奇的仓库(树形DP)
「题目背景」
小奇采的矿实在太多了,它准备在喵星系建个矿石仓库。令它无语的是,喵星系的货运飞船引擎还停留在上元时代!
「问题描述」
喵星系有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
下面一段话是出题人神秘而不失优雅的题解
算法1:
不会写函数的小伙伴们,我们只需要写个floyd,就有10分啦!
算法2:
在算法1的基础上,我们对每条边处理一下xor,就有20分啦!
算法3:
简单的树形DP,或者你会nlogn的dij,处理完每个点到其它点的最短路后再加上xor,那么这样就有30分啦!
算法4:
第4、5个点无需xor,那么我们树形DP扫一个节点与其它所有节点的路径长度之和,可以合并信息,最终均摊O(1),50分到手。
算法5:
第6个点xor 1,那么我们树形DP到一个点时记录有多少个0,多少个1,然后每当一条路径到2,那部分就再记录一个值,60分到手。
算法6:
如果你第6个点都过了,却没有满分,笨死啦!
一样的嘛,就是原来的“0”、“1”、大于等于2变成了0~16么~~
下面是自己的话:
既然是棵树,又要快速地求每个点的值,那一定是树形DP加上换根的操作啦~
但是异或m要怎么处理呢?可以观察数据规模,发现m最大最大也就15,换成二进制数也就是 1111,所以发现异或m最多只会对数字的后面4位造成影响(异或0甚至无法造成什么影响)
于是愉快地写出DP数组 f[i]和sz[i][0~15]
f表示此时以i为根的子树到i节点的距离之和(减去后缀后的和)
sz表示此时距离以j为后缀的共有几个
每一次向根节点方向转移时会加上一条边的长度,此时不同后缀距离的后缀会发生相应改变,然后更新父亲相应后缀的sz值。
然后f里统计的距离总和是抹掉所有后缀后的总和,即不考虑后缀的贡献。如有一个距离是 10111(2),抹去长度为2的后缀后就只剩下10100,然后将这个结果加到f数组里,到最后根节点统计最终答案时再考虑每个后缀的贡献,此时的sz数组就派上用场了(具体看代码)
还有一点,就是最后要把答案减去m,因为统计后缀贡献时,多加了自己到自己的距离(本来为0,xor m 后变成了m)。
代码如下
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> #define For(i,a,b) for(register int i=a;i<=b;++i)
#define Re register
#define Pn putchar('\n')
#define inf 0x7f7f7f
#define llg long long
using namespace std;
const int N=1e5+;
int sz[N][];
int head[N],nxt[N*],v[N*],cnt=;
llg w[N*],z,fn[N],f[N];
int n,m,x,y,ct,tot; inline void read(int &v){
v=;
char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')v=v*+c-'',c=getchar();
}
inline void read(llg &v){
v=;
char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')v=v*+c-'',c=getchar();
}
void write(llg x){
if(x>)write(x/);
int xx=x%;
putchar(xx+'');
} void add(int ux,int vx,llg wx){
cnt++;
nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx; w[cnt]=wx;
cnt++;
nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux; w[cnt]=wx;
} void DFS1(int x,int fa){
sz[x][]=;
for(Re int i=head[x];i;i=nxt[i]){
int vv=v[i];
if(vv==fa)continue;
DFS1(vv,x);
f[x]+=f[vv];
For(j,,tot){
int Nsm=j+w[i];
int Nst=Nsm & ct;
sz[x][Nst]+=sz[vv][j];
f[x]+=sz[vv][j]*(Nsm-Nst);
}
}
}
int Bsz[N][];
void DFS2(int x,int fa){ //换根
fn[x]=f[x];
For(st,,tot){
fn[x]+=(st^m)*sz[x][st];
}
For(st,,tot)Bsz[x][st]=sz[x][st];
llg Bf=f[x]; for(Re int i=head[x];i;i=nxt[i]){
int vv=v[i];
if(vv==fa)continue; int Nsm,Nst; For(st,,tot){
Nsm =st+w[i];
Nst=Nsm&ct;
sz[x][Nst]-=sz[vv][st];
f[x]-=sz[vv][st]*(Nsm-Nst);
} f[vv]=f[x];
For(st,,tot){
Nsm=st+w[i];
Nst=Nsm&ct;
sz[vv][Nst]+=sz[x][st];
f[vv]+=sz[x][st]*(Nsm-Nst);
} DFS2(vv,x); f[x]=Bf;
For(st,,tot)sz[x][st]=Bsz[x][st];
}
} int main(){
// freopen("warehouse.in","r",stdin);
// freopen("warehouse.out","w",stdout);
read(n); read(m); if(m==)ct=,tot=;
if(m==)ct=,tot=;
if(m==)ct=,tot=;
if(m==)ct=,tot=;
if(m>=)ct=,tot=; //简单粗暴的预处理 For(i,,n-){
read(x); read(y); read(z);
add(x,y,z);
}
DFS1(,);
DFS2(,);
For(i,,n){
write(fn[i]-m); Pn;
}
return ;
}
小奇的仓库(树形DP)的更多相关文章
- [CSP-S模拟测试]:小奇的仓库(warehouse)(树形DP)
题目背景 小奇采的矿实在太多了,它准备在喵星系建个矿石仓库.令它无语的是,喵星系的货运飞船引擎还停留在上元时代! 题目描述 喵星系有$n$个星球,星球以及星球间的航线形成一棵树.从星球$a$到星球$b ...
- 【换根DP】小奇的仓库
题目背景 小奇采的矿实在太多了,它准备在喵星系建个矿石仓库.令它无语的是,喵星系的货运飞船引擎还停留在上元时代! 题目内容 喵星系有\(n\)个星球,星球以及星球间的航线形成一棵树. 从星球\(a\) ...
- BZOJ4446:[SCOI2015]小凸玩密室(树形DP)
Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室. 每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...
- 【bzoj4550】小奇的博弈 博弈论+dp
题目描述 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边 是黑色棋子,相邻的棋子颜色不同. 小奇可以移动白色棋子,提比可以移动黑色的棋子, ...
- [CSP-S模拟测试]:小奇挖矿2(DP+赛瓦维斯特定理)
题目背景 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎. 题目描述 现在有$m+1$个星球,从左到右标号为$0$到$n$,小奇最初 ...
- bzoj 5072 小A的树 —— 树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5072 由于对于一个子树,固定有 j 个黑点,连通块大小是一个连续的范围: 所以记 f[i][ ...
- [IOI2008/BZOJ1791 岛屿](处理基环树的小技巧&基于bfs树形DP)
IOI2008/BZOJ1791 岛屿 题目大意是在一个基环树森林里求每一棵基环树的直径①的和. 其实就是树的直径的基环树升级版.我们先把环找出来,然后从环上的每一个节点x出发,并且不经过环上其他节点 ...
- LUOGU P4253 [SCOI2015]小凸玩密室(树形dp)
传送门 解题思路 玄学树形\(dp\),题目描述极其混乱...看错了两次题,设首先根据每次必须点完子树里的灯才能点别的,那么点灯情况只有两种,第一种是点到某一个祖先,第二种是点到某一个祖先的兄弟.所以 ...
- 小奇的仓库:换根dp
一道很好的换根dp题.考场上现场yy十分愉快 给定树,求每个点的到其它所有点的距离异或上m之后的值,n=100000,m<=16 只能线性复杂度求解,m又小得奇怪.或者带一个log像kx一样打一 ...
随机推荐
- wepy原理研究
像VUE一样写微信小程序-深入研究wepy框架 https://zhuanlan.zhihu.com/p/28700207 wepy原理研究 虽然wepy提升了小程序开发体验,但毕竟最终要运行在小程序 ...
- Dropout: A Simple Way to Prevent Neural Networks fromOverfitting
https://www.cs.toronto.edu/~hinton/absps/JMLRdropout.pdf Deep neural nets with a large number of par ...
- cenos 6.5 安装apache 2.4.28出现种问题
编译出错 configure: error: APR-util not found. Please read the documentation 解决办法 wget http://apache.fre ...
- 谈谈EJB是怎样公布Web Service的
定义 我们常常会听到.xx项目中用到了Web Service.那么.什么是Web Service呢? 首先让我们来了解一下Web Service.Web Service技术.就是能使得执行在不同机器上 ...
- java web项目初始化启动一个java方法
项目中需要一些初始化数据,或者加载中断的任务. 首先在web.xml中配置信息,配置在<web-app>中: <servlet> <servlet-name>Ini ...
- Machine Learning in Action(5) SVM算法
做机器学习的一定对支持向量机(support vector machine-SVM)颇为熟悉,因为在深度学习出现之前,SVM一直霸占着机器学习老大哥的位子.他的理论很优美,各种变种改进版本也很多,比如 ...
- 火狐浏览器使用firebug获取xpath和css path
工作中,常常会用到网页元素的定位方式,常用的有xpath和css path两种定位方式. 现在简单介绍如何使用工具自动生成元素的定位字符串. 首先介绍在火狐浏览器上使用FireBug及其扩展FireP ...
- FFmpeg big changes. ffmpeg 接口的一些改变
Big changes have been made from FFmpeg 0.5.1… Refer to http://cekirdek.pardus.org.tr/~ismail/ffmpeg- ...
- xml文件的解析(用dom4j解析)
有个第三方的包,用来解析.xml文件比较方便,它是DOM4J.由于是第三方的,所以要使用它就要先下载,并包含进来.步骤: 1.打开dom4j官网,这里下载最新版dom4j-2.1.1.jar. 2.新 ...
- Windows内存性能分析(一)内存泄漏
判断内存性能表现主要是为了解决如下两个问题: 1. 当前web应用是否存在内存泄漏,如果有,问题的程度有多大? 2. 如果web应用的代码无法进一步改进,当前web应用所在的服务器是否存在内存上的瓶颈 ...