Solution -「HDU 6643」Ridiculous Netizens
\(\mathcal{Description}\)
Link.
给定一棵含有 \(n\) 个结点的树,点 \(u\) 有点权 \(w_u\),求树上非空连通块的数量,使得连通块内点权积 \(\le m\)。
\(n\le2\times10^3\),\(m\le10^6\),\(w_u\in[1,m]\),数据组数 \(T\le10\)。
\(\mathcal{Solution}\)
很明显是点分,每次考虑跨当前分治重心 \(r\) 的所有连通块对答案的贡献。问题变为:求树上以 \(r\) 为根的满足条件的连通块数量。
一个简单的想法是以子树为子问题树上 DP,但是点权积的状态空间与子树大小完全无关,子树与子树的合并反而更加浪费时间,这提示我们,应该设计一种仅有单点更新的 DP 状态——以 DFN 为子问题 DP。
另一方面,由于运算全部是乘法,可以考虑整除分块的储存方式压缩状态树。令 \(f(u,i)\) 表示当 DFS 进行到某一时刻时,以 \(u\) 子树内已经被搜过的点为最大 DFN 点的连通块中,点权积在整除分块后被映射到 \(i\) 的方案数。进入 \(u\) 子树时用 \(u\) 的父亲更新 \(f(u)\),退出 \(u\) 子树时将 \(f(u)\) 上传给 \(u\) 的父亲。设树的大小为 \(s\),DP 的复杂度为 \(\mathcal O(s\sqrt m)\)。
最终,算法复杂度为 \(\mathcal O(Tn\sqrt m\log n)\)。
\(\mathcal{Code}\)
/*+Rainybunny+*/
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)
typedef long long LL;
const int MAXN = 2e3, MOD = 1e9 + 7, THRES = 1e3;
int n, m, thres, ecnt, val[MAXN + 5], head[MAXN + 5];
int siz[MAXN + 5], wgt[MAXN + 5], ans;
int f[MAXN + 5][THRES * 2 + 5], g[MAXN + 5][THRES * 2 + 5];
struct Edge { int to, nxt; } graph[MAXN * 2 + 5];
bool vis[MAXN + 5];
inline void chkmax(int& u, const int v) { u < v && (u = v); }
inline int imin(const int u, const int v) { return u < v ? u : v; }
inline void addeq(int& u, const int v) { (u += v) >= MOD && (u -= MOD); }
inline void link(const int u, const int v) {
graph[++ecnt] = { v, head[u] }, head[u] = ecnt;
graph[++ecnt] = { u, head[v] }, head[v] = ecnt;
}
inline void findG(const int u, const int fa, const int all, int& rt) {
siz[u] = 1, wgt[u] = 0;
for (int i = head[u], v; i; i = graph[i].nxt) {
if (!vis[v = graph[i].to] && v != fa) {
findG(v, u, all, rt), siz[u] += siz[v];
chkmax(wgt[u], siz[v]);
}
}
chkmax(wgt[u], all - siz[u]);
if (!rt || wgt[rt] > wgt[u]) rt = u;
}
inline void getDP(const int u, const int fa) {
int *fcur = f[u], *ffa = f[fa];
rep (i, 0, thres << 1) fcur[i] = 0;
if (!fa) fcur[val[u] <= thres ? val[u] : thres + m / val[u]] = 1;
else {
rep (i, 0, imin(thres, m / val[u])) {
int t = i * val[u];
addeq(fcur[t <= thres ? t : thres + m / t], ffa[i]);
}
rep (i, val[u], thres) {
addeq(fcur[thres + i / val[u]], ffa[thres + i]);
}
}
for (int i = head[u], v; i; i = graph[i].nxt) {
if (!vis[v = graph[i].to] && v != fa) {
getDP(v, u);
}
}
if (fa) rep (i, 0, thres << 1) addeq(ffa[i], fcur[i]);
}
inline void solve(const int u) {
// printf("!%d\n", u);
vis[u] = true, getDP(u, 0);
rep (i, 0, thres << 1) addeq(ans, f[u][i]);
for (int i = head[u], v, rt; i; i = graph[i].nxt) {
if (!vis[v = graph[i].to]) {
findG(v, 0, siz[v], rt = 0), solve(rt);
}
}
}
inline void allClear() {
ans = ecnt = 0;
rep (i, 1, n) head[i] = vis[i] = 0;
}
int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &m), thres = int(sqrt(1. * m));
allClear();
rep (i, 1, n) scanf("%d", &val[i]);
rep (i, 2, n) { int u, v; scanf("%d %d", &u, &v), link(u, v); }
int rt = 0; findG(1, 0, n, rt);
solve(rt), printf("%d\n", ans);
}
return 0;
}
Solution -「HDU 6643」Ridiculous Netizens的更多相关文章
- Solution -「HDU 6875」Yajilin
\(\mathcal{Description}\) Link.(HDU 裂开了先放个私链 awa.) 在一个 \(n\times n\) 的方格图中,格子 \((i,j)\) 有权值 \(w_ ...
- Solution -「HDU 5498」Tree
\(\mathcal{Description}\) link. 给定一个 \(n\) 个结点 \(m\) 条边的无向图,\(q\) 次操作每次随机选出一条边.问 \(q\) 条边去重后构成生成 ...
- Solution -「HDU 1788」CRT again
\(\mathcal{Description}\) Link. 解同余方程组: \[x\equiv m_i-a\pmod{m_i} \] 其中 \(i=1,2,\dots,n\). \ ...
- Solution -「HDU #6566」The Hanged Man
\(\mathcal{Description}\) Link. 给定一棵含 \(n\) 个点的树,每个结点有两个权值 \(a\) 和 \(b\).对于 \(k\in[1,m]\),分别求 \[ ...
- [HDU多校]Ridiculous Netizens
[HDU多校]Ridiculous Netizens 点分治 分成两个部分:对某一点P,连通块经过P或不经过P. 经过P采用树形依赖背包 不经过P的部分递归计算 树型依赖背包 v点必须由其父亲u点转移 ...
- Solution -「ARC 104E」Random LIS
\(\mathcal{Description}\) Link. 给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...
- Solution -「HDU」Professor Ben
Description 有 \(Q\) 个询问.每次给定一个正整数 \(n\),求它的所有因数的质因数个数的和. Solution 就讲中间的一个 Trick. 我们定义正整数 \(x\) 有 \(f ...
- Solution -「CTS 2019」「洛谷 P5404」氪金手游
\(\mathcal{Description}\) Link. 有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...
- Solution -「BZOJ 3812」主旋律
\(\mathcal{Description}\) Link. 给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...
随机推荐
- SQL高级优化(一)之MySQL优化
不同方案效率对比 MySQL各字段默认长度(一字节为8位) 整型: TINYINT 1 字节 SMALLINT 2 个字节 MEDIUMINT 3 个字节 INT 4 个字节 INTEGER 4 个字 ...
- Echart可视化学习(五)
文档的源代码地址,需要的下载就可以了(访问密码:7567) https://url56.ctfile.com/f/34653256-527823386-04154f 常见的数据可视化库: D3.js ...
- FIS 使用
从淘宝npm镜像安装fis $ npm install -g fis --registry=https://registry.npm.taobao.org 安装less插件 $ npm install ...
- 制作JavaCV应用依赖的基础Docker镜像(CentOS7+JDK8+OpenCV4)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 【get√】golang新手理解了一点点context
测试代码如下: package practice import ( "context" "log" //"fmt" "time&q ...
- golang中的GOPATH使用和简单项目配置
GOPATH 是 Go 语言的工作目录,他的值可以是一个目录路径,也可以是多个目录路径,每个目录都代表 go 语言的一个工作区. 我们开发 Golang 项目时,需要依赖一些别的代码包,这些包的存放路 ...
- 聊一聊如何用C#轻松完成一个SAGA分布式事务
背景 银行跨行转账业务是一个典型分布式事务场景,假设 A 需要跨行转账给 B,那么就涉及两个银行的数据,无法通过一个数据库的本地事务保证转账的 ACID ,只能够通过分布式事务来解决. 市面上使用比较 ...
- 第06讲:Flink 集群安装部署和 HA 配置
Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 第04讲:Flin ...
- 微服务架构 | 5.4 Sentinel 流控、统计和熔断的源码分析
目录 前言 1. Sentinel 的自动装配 1.2 依赖引入 1.3 SentinelWebAutoConfiguration 配置类 1.4 CommonFilter 过滤器 1.5 小结 2. ...
- 洛谷P1002过河卒(60分)
逻辑没问题,运行超时,得分60 写注释了,不多解释 import java.util.Scanner; public class D1 { static int a,b,c,d,con; //棋盘大小 ...