小奇的仓库(树形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一样打一 ...
随机推荐
- 九度OJ 1115:数字求和 (基础题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2396 解决:1507 题目描述: 给定一个正整数a,以及另外的5个正整数,问题是:这5个整数中,小于a的整数的和是多少? 输入: 输入一行 ...
- JAVA工厂方法模式(Factory Method)
1.普通工厂模式 普通工厂模式:就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建. 1-1.建立Sender接口 public interface Sender { public void ...
- ElasticSearch(八)关于document的一些知识点
先查看一条数据: GET /ecommerce/product/5 { "_index" : "ecommerce", "_type" : ...
- FIL代币是什么?
自从比特币价格暴涨.区块链技术火了以后,出现了币圈,币圈中有各种各样的代币,本文就和大家介绍其中的FIL代币相关内容,希望能帮助大家一点一点的了解币圈. IPFS与Filecoin的关系 ...
- window cmd 自动补全
1. 用命令里输入regedit注册表 WIN+R 快捷输入 regedit regedit2. 键值改为9(十进制) HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Co ...
- HTML5 实现文件拖放上传
1. [图片] 5375acf5gw1dusqsscfksj.jpg 2. [代码][HTML]代码 <!DOCTYPE html><html lang="en" ...
- hdu 1004 Let the Balloon Rise 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1004 用STL 中的 Map 写的 #include <iostream> #includ ...
- 关于RHEL5中yum挂载iso源引起的问题(转)
今天在虚机上通过yum挂载iso源来安装rpm包,但提示错误,内容见下面.之前也有过这样的操作, mount后,修改repo文件,然后就可以yum install rpm包了:过程很简单啊.不知道这 ...
- syslog格式
转自:http://wly719.iteye.com/blog/1827394 1.syslog格式介绍 在Unix类操作系统上,syslog广泛 应用于系统日志.syslog日志消息既可以记录在本地 ...
- Dom4J 解析xml ,类查询
/** * 从XML文件比对,传入provinceId 返回 provinceShortName * @param provinceid * @return */ public static Stri ...