当前位置: 首页 > news >正文

LG P5138 fibonacci Solution

Description

给你一棵以 111 为根的树 TTT,点有点权 wiw_iwi,初始为 000
dep⁡(u)\operatorname{dep}(u)dep(u)uuu 的深度(不带权),fib⁡(n)\operatorname{fib}(n)fib(n) 为斐波那契数列第 nnn 项(nnn 可为负数)。
执行 qqq 次操作,操作分两种:

  • U x k:对每个 u∈subtree⁡(x)u\in \operatorname{subtree}(x)usubtree(x) 执行 wu←wu+fib⁡(dep⁡(u)−dep⁡(x)+k)w_u\gets w_u + \operatorname{fib}(\operatorname{dep}(u)-\operatorname{dep}(x)+k)wuwu+fib(dep(u)dep(x)+k)
  • Q x y:查询链 x→yx\to yxy 上的点权和,对 (109+7)(10^9+7)(109+7) 取模。

Limitations

1≤n,q≤1051\le n,q\le 10^51n,q105
1≤u,v≤n1\le u,v\le n1u,vn
1≤k≤1081\le k\le 10^81k108
1s,125MB1\text{s},125\text{MB}1s,125MB

Solution

根据 fib⁡\operatorname{fib}fib 的性质,有:
fib⁡(n+m)=fib⁡(n−1)×fib⁡(m)+fib⁡(n)×fib⁡(m+1)\operatorname{fib}(n+m)=\operatorname{fib}(n-1)\times\operatorname{fib}(m)+\operatorname{fib}(n)\times\operatorname{fib}(m+1)fib(n+m)=fib(n1)×fib(m)+fib(n)×fib(m+1)

所以对于每次 U 操作,点 uuu 增加的值为:
fib⁡(dep⁡(u)−1)×fib⁡(k−dep⁡(x))+fib⁡(dep⁡(u))×fib⁡(k−dep⁡(x)+1)\operatorname{fib}(\operatorname{dep}(u)-1)\times\operatorname{fib}(k-\operatorname{dep}(x))+\operatorname{fib}(\operatorname{dep}(u))\times\operatorname{fib}(k-\operatorname{dep}(x)+1)fib(dep(u)1)×fib(kdep(x))+fib(dep(u))×fib(kdep(x)+1)

那么每个点的权值就可以写成 fib⁡(dep⁡(u)−1)×p+fib⁡(dep⁡(u))×q\operatorname{fib}(\operatorname{dep}(u)-1)\times p+\operatorname{fib}(\operatorname{dep}(u))\times qfib(dep(u)1)×p+fib(dep(u))×q 的形式,用线段树维护 p,qp,qp,q 和答案即可。

查询时直接用树剖,求 fib⁡(n)\operatorname{fib}(n)fib(n) 可以用矩阵或扩域,处于常数考虑可以选择后者。

那么就做完了,时间复杂度 O(qlog⁡2nlog⁡V)O(q\log^2 n\log V)O(qlog2nlogV)

Code

粘了一堆板子,所以省略了一部分,代码中的深度从 000 开始。

#include <bits/stdc++.h>
using namespace std;using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;template<class T>
bool chmax(T &a, const T &b){if(a < b){ a = b; return true; }return false;
}template<class T>
bool chmin(T &a, const T &b){if(a > b){ a = b; return true; }return false;
}template <int MOD>
struct modint {};
using Z = modint<1000000007>;template<int S>
struct quad {};using Q5 = quad<5>;
const Z half = Z(2).inv();template<class T> 
Z fib(T n) {if (n == 0) return 0;Q5 phi = Q5(half, half), psi = Q5(half, -half), sqrt5 = Q5(0, 1);if (n > 0) return ((phi.pow(n) - psi.pow(n)) / sqrt5).value();else {Z res = ((phi.pow(-n) - psi.pow(-n)) / sqrt5).value();return ((-n) & 1) ? res : -res;}
}template<class Info, class Tag>
struct lazy_segment{};struct tag {Z a, b;inline tag() : tag(0, 0) {}inline tag(Z a, Z b) : a(a), b(b) {}inline void apply(const tag& t) { a += t.a, b += t.b; }
};struct info {Z a, b, sum;inline info() {}inline info(Z a, Z b, Z sum) : a(a), b(b), sum(sum) {}inline void apply(const tag& t) { sum += t.a * a + t.b * b; }inline info operator+(const info& rhs) const {return {a + rhs.a, b + rhs.b, sum + rhs.sum};}
};signed main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n, q;cin >> n >> q;vector<vector<int>> g(n);for (int i = 0, u, v; i < n - 1; i++) {cin >> u >> v, u--, v--;g[u].push_back(v);g[v].push_back(u);}vector<int> dep(n), par(n), siz(n), son(n, -1);auto dfs = [&](auto&& self, int u, int fa) -> void {siz[u] = 1, par[u] = fa;for (auto v : g[u]) {if (v == fa) continue;dep[v] = dep[u] + 1;self(self, v, u);siz[u] += siz[v];if (son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v;}};int clock = 0;vector<int> dfn(n), top(n);vector<info> seq(n);auto dfs2 = [&](auto&& self, int u, int topf) -> void {seq[dfn[u] = clock++] = {fib(dep[u]), fib(dep[u] + 1), 0};top[u] = topf;if (~son[u]) self(self, son[u], topf);for (auto v : g[u]) {if (v == par[u] || v == son[u]) continue;self(self, v, v);}};dfs(dfs, 0, 0);dfs2(dfs2, 0, 0);lazy_segment<info, tag> tree(seq);auto ask = [&](int u, int v) {Z res = 0;while (top[u] != top[v]) {if (dep[top[u]] < dep[top[v]]) swap(u, v);res += tree.query(dfn[top[u]], dfn[u]).sum;u = par[top[u]];}if (dfn[u] > dfn[v]) swap(u, v);res += tree.query(dfn[u], dfn[v]).sum; return res;};auto upd = [&](int u, i64 k) {tree.apply(dfn[u], dfn[u] + siz[u] - 1,{fib(k - dep[u] - 1), fib(k - dep[u])}); 	};for (int i = 0; i < q; i++) {char op; cin >> op;if (op == 'U') {int u; i64 k;cin >> u >> k, u--;upd(u, k);}else {int u, v;cin >> u >> v, u--, v--;cout << ask(u, v) << '\n';}}return 0;
}
http://www.dtcms.com/a/388786.html

相关文章:

  • 删除UCPD监控服务或者监控驱动
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(33):文法運用第10回1+(考え方14)
  • 向量技术研究报告:从数学基础到AI革命的支柱
  • 802.1x和802.1Q之间关联和作用
  • 基于大模型多模态的人体体型评估:从“尺码测量”到“视觉-感受”范式
  • 更符合人类偏好的具身导航!HALO:面向机器人导航的人类偏好对齐离线奖励学习
  • Transformer多头注意力机制
  • git 分支 error: src refspec sit does not match any`
  • VN1640 CH5 I/O通道终极指南:【VN1630 I/O功能在电源电压时间精确度测试中的深度应用】
  • qt QHorizontalBarSeries详解
  • 半导体制造的芯片可靠性测试的全类别
  • MySQL 索引详解:原理、类型与优化实践
  • AI 重塑就业市场:哪些岗位将被替代?又会催生哪些新职业赛道?
  • mysql表分区备份太慢?如何精准“狙击”所需数据?
  • InVEST实践及在生态系统服务供需、固碳、城市热岛、论文写作等实际项目中应用
  • 数据库视图详解
  • C#并行处理CPU/内存监控:用PerformanceCounter实时监控,避免资源过载(附工具类)
  • 数据结构初阶——红黑树的实现(C++)
  • PS练习1:将风景图放到相框中
  • Seedream 4.0深度评测:新一代AI图像创作的革命性突破
  • Python中的异常和断言
  • java求职学习day32
  • 内存一致性模型(Memory Consistency Model)及其核心难度
  • Archery:一个免费开源的一站式SQL审核查询平台
  • 【中科院宁波材料技术与工程研究所主办】第五届机械自动化与电子信息工程国际学术会议(MAEIE 2025)
  • 政府支持再造视角下A区政府采购数字化发展问题及对策
  • 第三章:新婚
  • python+vue小区物业管理系统设计(源码+文档+调试+基础修改+答疑)
  • Android系统框架知识系列(二十二):Storage Manager Service - Android存储系统深度解析
  • 模板的特化详解