小奇的仓库(树形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一样打一 ...
随机推荐
- 2018.11.23-day27 面向对象(大总结)
1. 2个内置函数 2.反射 3.内置方法 4.面向对象大总结 思维导图地址:https://www.processon.com/view/link/5bfcfd62e4b0ef094cbf04a7 ...
- keybd_event、SendInput笔记
void keybd_event(BYTE bVk, BYTE bScan, DWORD dwFlags, ULONG_PTR dwExtraInfo); bVk:虚拟键码 bScan:键的硬件扫描码 ...
- 关于WordPress后台设置中的WordPress地址和站点地址的解读
今天我在TeachCourse博客中不小心把WordPress地 址和站点地址都改为了http://www.qgjie123.com,结果重新刷新TeachCourse博客页面的时候,页面排版错乱的情 ...
- MQ发送的消息都到了死信队列中了
MQ在发送消息的时候,设置的过期时间太短.(昨天项目上线遇到了,开发中也遇到一次.)谨记!!!
- javascript fetch 跨域请求时 session失效问题
javascript 使用fetch进行跨域请求时默认是不带cookie的,所以会造成 session失效. fetch(url, { method: 'POST', credentials: 'in ...
- 代码空间项目 -- InstantiationException的异常
java.lang.InstantiationException实例化异常.当试图通过newInstance()方法创建某个类的实例,而该类是一个抽象类或接口时,抛出该异常. 这次项目中查询type时 ...
- Codeforces Round #303 (Div. 2) D. Queue —— 贪心
题目链接:http://codeforces.com/problemset/problem/545/D 题解: 问经过调整,最多能使多少个人满意. 首先是排序,然后策略是:如果这个人对等待时间满意,则 ...
- The import ....cannot be resolved 解决方法
1:右击项目build path>configure build path>libraries看有没感叹号什么的不正常的lib,移除掉 2:点击项目的build path>confi ...
- multi_socket
threading_test.py #threading #为什么在命令行可以执行,F5不能执行 #线程处理能导致同步问题 from socketserver import TCPServer,Thr ...
- css 内容超出宽度自动换行
1. word-break:break-all;只对英文起作用,以字母作为换行依据2. word-wrap:break-word; 只对英文起作用,以单词作为换行依据 PS:要设定宽度!