1 条题解
-
0
自动搬运
来自洛谷,原作者为

weilycoder
Per Aspera Ad Astra搬运于
2025-08-24 22:26:55,当前版本为作者最后更新于2024-09-26 18:11:14,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
法 1
题目要求的实际上就是这样的函数的复合:
$$\begin{aligned} f(x)&=\left\lfloor\dfrac{x}{p}\right\rfloor+q \\ &=\left\lfloor\dfrac{x+pq}{p}\right\rfloor \end{aligned} $$所以我们求一下 看看啥样:
$$\begin{aligned} f_2(f_1(x))&=\left\lfloor\dfrac{\left\lfloor\frac{x+p_1q_1}{p_1}\right\rfloor+p_2q_2}{p_2}\right\rfloor \\ &=\left\lfloor\dfrac{x+p_1q_1+p_1p_2q_2}{p_1p_2}\right\rfloor \end{aligned} $$注意到函数始终是 的形式,我们考虑线段树维护。
但是由于复合后的 和 要做乘法,数大的时候会炸掉,考虑用
long double乱搞一下。我们把函数写成 的形式,这里 均为实数,复合的形式是
$$f_2(f_1(x))=\left\lfloor\dfrac{\left\lfloor\frac{x}{a_1}+b_1\right\rfloor}{a_2}+b_2\right\rfloor=\left\lfloor\dfrac{x}{a_1a_2}+\left(\dfrac{b_1}{a_2}+b_2\right)\right\rfloor $$上线段树即可。
法 2
观察一下 ,不妨改成 的形式,其中 。
由于 ,我们讨论 是否大于 。
若 ,暴力维护。
若 ,由于 ,原函数就是
$$f(x)=\begin{cases} b&,x>a-c \\ b+1&,\text{otherwise} \end{cases} $$这个玩意不好和其他函数复合,不妨把它写成
$$f(x)=\left\lfloor\dfrac{x+\max(10^6+1-(a-c),0)}{10^6+1}\right\rfloor+b $$容易证明在 时两个函数是同一函数。
上线段树维护。
Code
这是方法 1 的代码,被 Hack 了叫我一声,有 dalao 证明正确了也叫我一声。
#include <cmath> #include <iostream> using namespace std; const int N = 1e5 + 7; int n, m, P[N], Q[N]; struct node_t { long double a, b; inline node_t operator*(const node_t &g) const { return {a * g.a, g.b / a + b}; } inline int64_t operator()(int x) const { return floorl(x / a + b); } } tree[N << 2]; #define lc (p << 1) #define rc (p << 1 | 1) void build(int p, int l, int r) { if (l == r) { tree[p] = {(long double)P[l], (long double)Q[l]}; return; } int mid = ((r - l) >> 1) + l; build(lc, l, mid), build(rc, mid + 1, r); tree[p] = tree[rc] * tree[lc]; } void update(int p, int l, int r, int x, int a, int b) { if (l == r) { tree[p] = {(long double)a, (long double)b}; return; } int mid = ((r - l) >> 1) + l; if (x <= mid) update(lc, l, mid, x, a, b); else update(rc, mid + 1, r, x, a, b); tree[p] = tree[rc] * tree[lc]; } node_t ask(int p, int l, int r, int s, int t) { if (s <= l && r <= t) return tree[p]; int mid = ((r - l) >> 1) + l; node_t res{(long double)1, (long double)0}; if (s <= mid) res = ask(lc, l, mid, s, t) * res; if (t > mid) res = ask(rc, mid + 1, r, s, t) * res; return res; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> P[i]; for (int i = 1; i <= n; ++i) cin >> Q[i]; build(1, 1, n); while (m--) { char op; cin >> op; switch (op) { case 'm': { int i, p, q; cin >> i >> p >> q; update(1, 1, n, i, p, q); break; } case 'q': { int x, s, t; cin >> x >> s >> t; cout << ask(1, 1, n, s, t)(x) << '\n'; } } } return 0; }
- 1
信息
- ID
- 6288
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者