2021“MINIEYE杯”中国大学生算法设计超级联赛(3)1011. Segment Tree with Pruning(记忆化搜索)
Problem Description
Chenjb is struggling with data stucture now. He is trying to solve a problem using segment tree. Chenjb is a freshman in programming contest, and he wrote down the following C/C++ code and ran ''𝙽𝚘𝚍𝚎* 𝚛𝚘𝚘𝚝 = 𝚋𝚞𝚒𝚕𝚍(𝟷, 𝚗)'' to build a standard segment tree on range [1,n]:
Node* build(long long l, long long r) {
Node* x = new(Node);
if (l == r) return x;
long long mid = (l + r) / 2;
x -> lchild = build(l, mid);
x -> rchild = build(mid + 1, r);
return x;
}
Chenjb submitted his code, but unfortunately, got MLE (Memory Limit Exceeded). Soon Chenjb realized that his program will new a large quantity of nodes, and he decided to reduce the number of nodes by pruning:
Node* build(long long l, long long r) {
Node* x = new(Node);
if (r - l + 1 <= k) return x;
long long mid = (l + r) / 2;
x -> lchild = build(l, mid);
x -> rchild = build(mid + 1, r);
return x;
}
You know, Chenjb is a freshman, so he will try different values of k to find the optimal one. You will be given the values of n and k, please tell him the number of nodes that will be generated by his new program.
Input
The first line contains a single integer T (1≤T≤10000), the number of test cases. For each test case:
The only line contains two integers n and k (1≤k≤n≤1018), denoting a query.
Output
For each query, print a single line containing an integer, denoting the number of segment tree nodes.
Sample Input
3
100000 1
100000 50
1000000000000000000 1
Sample Output
199999
4095
1999999999999999999
sb了,一开始想能不能打表推式子,后来想到了记忆化又不知道咋写...
可以发现,给定一段区间[l, r],这个区间中的能生成的节点数和左右端点大小无关,只和r - l + 1有关,且不同的区间长度并不是很多,因此考虑记录长度对应的生成节点数。
#include <bits/stdc++.h>
using namespace std;
#define int long long
long long n, k;
long long cnt = 0;
map<long long, long long> mp;
long long ans = 0;
long long dfs(long long l, long long r) {
cnt++;
if(r - l + 1 <= k) {
return 1;
}
if(mp.find(r - l + 1) != mp.end()) {
long long tmp = mp[r - l + 1];
return tmp;
}
long long tmp = 1;
long long mid = (l + r) >> 1;
tmp += dfs(l, mid);
tmp += dfs(mid + 1, r);
mp[r - l + 1] = tmp;
return tmp;
}
signed main() {
int t;
cin >> t;
while(t--) {
cnt = 0;
ans = 0;
mp.clear();
cin >> n >> k;
cout << dfs(1, n) << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2020-07-27 HDU6768 The Oculus(Hash)
2020-07-27 HDU6672 Lead of Wisdom(爆搜)