HDU - 6643: Ridiculous Netizens(点分治+依赖背包+空间优化)
题意:给定带点权的树,问多少个连通块,其乘积<=M; N<=2000,M<1e6;
思路:连通块-->分治; 由于普通的树DP在合并的时候复杂度会高一个M,所以用依赖背包来做。 (当然,由于体积分布是离散的,可能有些选手用map也可以过,这样避免了每次都for(i,1,M),取决于数据吧)。
那么现在的复杂度就是O(NlogN*M) ,空间为O(N*M),尚待优化。
这里非常巧妙的把<sqrt(M)的和大于sqrt(M)的分开保存,那么前者就是正常的背包,表示背包里存了多少东西; 后者可以看成背包里最多还可以存多少东西。 那么复杂度就变成了O(Nsqrt(M)logN); 空间O(Nsqrt(M)); 就可以过了。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=;
const int Mod=1e9+;
int w[maxn],ans;
int dp1[maxn][maxn>>],dp2[maxn][maxn>>],dp[maxn][maxn];
int Laxt[maxn],Next[maxn<<],To[maxn<<],cnt;
int son[maxn],sz[maxn],vis[maxn],rt,SZ;
int times,p[maxn],M,qM;
void MOD(int &X){if(X>Mod) X-=Mod;}
void add(int u,int v)
{
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
}
void getroot(int u,int f) //得到重心
{
sz[u]=; son[u]=;
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i]; if(vis[v]||v==f) continue;
getroot(v,u);
sz[u]+=sz[v];
son[u]=max(son[u],sz[v]);
}
son[u]=max(son[u],SZ-son[u]);
if(rt==||son[u]<son[rt]) rt=u;
}
void dfs(int u,int f) //得到dfs序。
{
p[++times]=u; sz[u]=;
for(int i=Laxt[u];i;i=Next[i]){
if(To[i]==f||vis[To[i]]) continue;
dfs(To[i],u);
sz[u]+=sz[To[i]];
}
}
void cal()
{
rep(i,,times+){
memset(dp1[i],,sizeof(dp1[i]));
memset(dp2[i],,sizeof(dp2[i]));
}
dp1[times+][]=;
for(int i=times;i>=;i--){
int x=w[p[i]];
rep(j,,min(qM,M/x)) {
int k=j*x;
if(k<=qM) MOD(dp1[i][k]+=dp1[i+][j]);
else MOD(dp2[i][M/k]+=dp1[i+][j]);
}
rep(j,x,qM) {
MOD(dp2[i][j/x]+=dp2[i+][j]);
}
rep(j,,qM) MOD(dp1[i][j]+=dp1[i+sz[p[i]]][j]);
rep(j,,qM) MOD(dp2[i][j]+=dp2[i+sz[p[i]]][j]);
}
rep(i,,qM) MOD(ans+=dp1[][i]);
rep(i,,qM) MOD(ans+=dp2[][i]);
ans--; //减去为空的情况
if(ans<) ans+=Mod;
}
void solve(int u) //分治
{
vis[u]=;
times=; dfs(u,);
cal();
for(int i=Laxt[u];i;i=Next[i]){
if(vis[To[i]]) continue;
SZ=sz[To[i]]; rt=;
getroot(To[i],);
solve(rt);
}
}
int main()
{
int T,N,u,v;
scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&M); qM=sqrt(M);
rep(i,,N) scanf("%d",&w[i]);
rep(i,,N) Laxt[i]=vis[i]=; cnt=;
rep(i,,N-){
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
SZ=N; rt=; getroot(,);
ans=; solve(rt);
printf("%d\n",ans);
}
return ;
}
HDU - 6643: Ridiculous Netizens(点分治+依赖背包+空间优化)的更多相关文章
- Hdu 6268 点分治 树上背包 bitset 优化
给你一颗大小为n(3000)的树,树上每个点有点权(100000),再给你一个数m(100000) i为1~m,问树中是否存在一个子图,使得权值为i. 每次solve到一个节点 用一个bitset维护 ...
- [HDU多校]Ridiculous Netizens
[HDU多校]Ridiculous Netizens 点分治 分成两个部分:对某一点P,连通块经过P或不经过P. 经过P采用树形依赖背包 不经过P的部分递归计算 树型依赖背包 v点必须由其父亲u点转移 ...
- 依赖背包优化——hdu1561
傻逼依赖背包的优化 #include<bits/stdc++.h> using namespace std; #define N 205 ]; int head[N],tot,n,m,a[ ...
- 依赖背包变形——poj1947(经典)
/*这题显然不适用依赖背包的优化,因为不能保证根是必选的,但是可以按照常规依赖背包的思路进行转移,即每次对一个儿子进行C^2的转移 还是树形的背包,dp[u][j]表示u的子树里,切割出一个大小为j的 ...
- 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)
The Ghost Blows Light Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The t ...
- BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)
BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...
- hdu 1561 The more, The Better (依赖背包 树形dp)
题目: 链接:点击打开链接 题意: 非常明显的依赖背包. 思路: dp[i][j]表示以i为根结点时攻击j个城堡得到的最大值.(以i为根的子树选择j个点所能达到的最优值) dp[root][j] = ...
- HDU 3449 依赖背包
这道题虽然水水的,但是还是成功地给我增加了10多个WA. 最开始拿着题,一看,依赖背包嘛~直接DFS树形DP嗨起来,甚至连内存都没有算一下,3MLE: 然后又仔细看了一下题,没有必要用树形背包来做嘛, ...
- HDU 2159 FATE(二维费用背包)
FATE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
随机推荐
- Qt 实现超时锁屏
最近使用Qt实现超时锁屏的功能(工控机触摸屏),当手长时间不触摸屏幕的时候,程序超时会显示锁屏窗口. 一.效果 主窗口超时显示锁屏窗口: 系统窗口超时显示锁屏窗口: 二.实现思路 首先开启一个线程用于 ...
- Shell脚本之三 传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n.n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推-- 实例 向脚本传递三个参数,并分 ...
- 关于Class: ES6 JavaScript的class的静态方法、属性和实例属性。
1.什么叫做静态方法? 1.1.类相当于实例的原型, 所有在类中定义的方法, 都会被实例继承.如果在一个方法前,加上Static关键字,就表示该方法不会被继承,而是直接通过类来调用,这被称为 “静态方 ...
- python入门之函数的嵌套
目录 函数的嵌套调用 函数的嵌套定义 函数的嵌套调用 在函数内调用函数 def index(): print('from index') def func(): index() print('from ...
- Springboot Actuator之十二:actuator aop
前言spring 中aop是一个核心概念,spring boot 是如何实现自动化配置的?现在我们就来分析一下 解析spring boot 中自动化配置是读取/META-INF/spring.fact ...
- VBA对象模型
https://www.processon.com/view/link/5d974da6e4b07a0a4d4a098a
- kubernetes 1.15 有哪些让人眼前一亮的新特性?
原文链接:kubernetes 1.15 有哪些让人眼前一亮的新特性? 2019 年 6 月 20 日,Kubernetes 重磅发布了 1.15 版本,不过笔者忙到现在才有空认真来看一下到底更新了哪 ...
- FusionInsight大数据开发---Redis应用开发
Redis应用开发 要求: 了解Redis应用场景 掌握Redis二次开发环境搭建 掌握Redis业务开发 Redis简介 Redis是一个基于网络的,高性能key-value内存数据库 Redis根 ...
- [Leetcode] Binary Tree Pruning
題目是說,如果左右子樹都不存在又自已為0,就去掉那個子樹(設為null) recursive後序,左子樹,右子樹,然後是根 自已同時又是別人的子樹,所以要告訢根自已是不是存在 從a開始,左右子樹都不存 ...
- Linux中的RCU的那点事
原文:https://zhuanlan.zhihu.com/p/67520807 今天来讲一下这Linux内核中的RCU(Read Copy Update,读复制更新)机制. 我主要参考的 ...