CF1917F Construct Tree 题解
题目链接:https://codeforces.com/contest/1917/problem/F
题意
有
题解
首先当然要存在一个边集
考虑对于一个给定的
- 存在一种划分
,使 。
考虑如何计算。将
-
; -
。
对右侧预处理背包,计算
时间复杂度的瓶颈在于双背包的转移和位向量卷积计算。使用 bitset
加速计算,则它们都可以在
代码实现
#include <bits/stdc++.h> using namespace std; using i64 = int64_t; using bs = bitset<2023>; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, d; cin >> n >> d; vector<int> l(n); for (int &x : l) cin >> x; ranges::sort(l); int s = accumulate(l.begin(), l.end(), 0); if (s == d) return void(cout << "Yes\n"); vector suf(n + 1, bs(1)); for (int i = n - 1; i >= 0; i--) { suf[i] = suf[i + 1] | (suf[i + 1] << l[i]); } bool ans = false; vector dp(d + 1, bs(0)); dp[0][0] = 1; for (int i = 0; i < n; i++) { int x = l[i]; s -= x; for (int s1 = d; s1 >= 0; s1--) { dp[s1] |= dp[s1] << x; if (s1 >= x) { dp[s1] |= dp[s1 - x]; } } bs vis{0}, pre{0}; for (int j = 0; j <= d - s; j++) pre[j] = dp[j][d - s - j]; // convolution (suf[i+1], pre) for (int j = 0; j <= s && j <= d / 2; j++) vis[j] = (pre & (suf[i + 1] >> (s - j))).any(); for (int j = s; j <= d / 2; j++) vis[j] = (pre & (suf[i + 1] << (j - s))).any(); for (int s1 = x; s1 <= d / 2; s1++) { ans |= vis[s1]; } } cout << (ans ? "Yes" : "No") << "\n"; }
分类:
做题记录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话