Nobody is needed
赛时没看 F,写完 E 就没时间了,唉唉,唉唉唉唉。
思路是 t 宝的代码。
Solution
考虑只有一组询问
此时显然可以 dp,设
得到方程
答案即为
对于原问题,考虑扫描线。
发现枚举
假设此时枚举到
将
如果直接按之前那样枚举的话,复杂度会炸到
这些数每个会有一个增量,根据之前的 dp,发现增量也可以 dp 算出来,只需要将方程改成
优化这个过程,可以通过先枚举
算出增量后,用树状数组维护
一轮枚举倍数是
struct BIT {
int n;
vector<ll> c;
BIT(int _n) {
n = _n;
c.resize(n + 1, 0);
}
void add(int x, int v) {
for (; x <= n; x += x & -x) c[x] += v;
}
ll query(int x) {
ll res = 0;
for (; x; x -= x & -x) res += c[x];
return res;
}
ll query(int l, int r) {
l --;
return query(r) - query(l);
}
};
void solve() {
int n, m;
cin >> n >> m;
vector<int> a(n + 1), p(n + 1);
for (int i = 1; i <= n; i ++) {
cin >> a[i];
p[a[i]] = i;
}
vector<vector<pair<int, int>>> qry(n + 1);
for (int i = 1; i <= m; i ++) {
int l, r;
cin >> l >> r;
qry[l].emplace_back(r, i);
}
vector<ll> ans(m + 1);
vector<ll> g(n + 1);
BIT bit(n);
for (int l = n; l >= 1; l --) {
int x = a[l];
g[x] = 1;
for (int i = x; i <= n; i += x) {
if (p[i] < p[x]) continue;
for (int j = i + i; j <= n; j += i) {
if (p[j] < p[i]) continue;
g[j] += g[i];
}
}
for (int i = x; i <= n; i += x) {
if (p[i] < p[x]) continue;
bit.add(p[i], g[i]);
g[i] = 0;
}
for (auto [r, id] : qry[l]) ans[id] = bit.query(r);
}
for (int i = 1; i <= m; i ++) cout << ans[i] << " \n"[i == m];
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现