题目描述
小 C 最近在学习线性函数,线性函数可以表示为:
f
(
x
)
=
k
∗
x
+
b
f(x)=k*x+b
f(x)=k∗x+b
现在小 C 面前有
n
n
n 个线性函数
f
i
(
x
)
=
k
i
∗
x
+
b
i
f_i(x)=k_i*x+b_i
fi(x)=ki∗x+bi,他对这
n
n
n 个线性函数执行
m
m
m 次操作,每次可以:
1 M i k b
代表把第
i
i
i 个线性函数改为
f
i
(
x
)
=
k
∗
x
+
b
f_i(x)=k*x+b
fi(x)=k∗x+b
2 Q l r x
返回
f
r
(
f
r
−
1
(
⋯
(
f
l
(
x
)
)
)
m
o
d
1
0
9
+
7
f_r(f_{r-1}(\cdots(f_l(x))) \mod 10^9+7
fr(fr−1(⋯(fl(x)))mod109+7
题解
考虑到三个线性函数
k
1
∗
x
+
b
1
k_1 * x + b_1
k1∗x+b1,
k
2
∗
x
+
b
2
k_2 * x + b_2
k2∗x+b2,
k
3
∗
x
+
b
3
k_3 * x + b_3
k3∗x+b3。
如果先复合前两个函数,后复合第三个函数的结果是:
k
3
∗
(
k
2
∗
(
k
1
∗
x
+
b
1
)
+
b
2
)
+
b
3
=
k
1
∗
k
2
∗
k
3
∗
x
+
b
1
∗
k
2
∗
k
3
+
b
2
∗
k
3
+
b
3
k_3*(k_2*(k_1*x+b_1)+b_2)+b_3=k_1*k_2*k_3*x+b_1*k_2*k_3+b_2*k_3+b_3
k3∗(k2∗(k1∗x+b1)+b2)+b3=k1∗k2∗k3∗x+b1∗k2∗k3+b2∗k3+b3。
如果先复合后两个函数,,再复合第一个函数的结果是: k 3 ( k 2 ∗ x + b 2 ) + b 3 = k 2 ∗ k 3 ∗ x + b 2 ∗ k 3 + b 3 = k 1 ∗ k 2 ∗ k 3 ∗ x + b 1 ∗ k 2 ∗ k 3 + b 2 ∗ k 3 + b 3 k_3(k_2*x+b_2)+b_3=k_2*k_3*x+b_2*k_3+b_3=k_1*k_2*k_3*x+b_1*k_2*k_3+b_2*k_3+b_3 k3(k2∗x+b2)+b3=k2∗k3∗x+b2∗k3+b3=k1∗k2∗k3∗x+b1∗k2∗k3+b2∗k3+b3。
可以发现两个结果是一样的,所以函数的复合满足结合律。那么,就可以利用线段树维护区间的复合函数,这样就可以求出答案了。
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
# define int long long
# define rd(t) read <t> ()
# define mem(a, b) memset (a, b, sizeof (a))
# define fi first
# define se second
# define lc u << 1
# define rc u << 1 | 1
# define debug printf ("debug\n")
const int N = 200005, mod = 1e9 + 7;
template <typename tr> inline tr read ()
{
tr s = 0; int w = 1; char c = getchar ();
for (; !isdigit (c); c = getchar ()) { if (c == '-') w = -1; }
for (; isdigit (c); c = getchar ()) s = (s << 1) + (s << 3) + c - '0';
return s * w;
}
int n, m;
int k[N], b[N];
char s[10];
struct tree
{
int l, r, k, b;
tree () { k = 1, b = 0; }
tree operator + (const tree &t) const
{
tree ans;
ans.k = (k * t.k) % mod; ans.b = ((b * t.k) % mod + t.b) % mod;
return ans;
}
} tr[N << 2];
void pushup (int u)
{
tr[u].k = (tr[lc].k * tr[rc].k) % mod;
tr[u].b = ((tr[lc].b * tr[rc].k) % mod + tr[rc].b) % mod;
}
void build (int u, int l, int r)
{
tr[u].l = l, tr[u].r = r;
if (l == r)
{
tr[u].k = k[l] % mod, tr[u].b = b[l] % mod;
return;
}
int mid = l + r >> 1;
build (lc, l, mid), build (rc, mid + 1, r);
pushup (u);
}
void modify (int u, int x, int k, int b)
{
int l = tr[u].l, r = tr[u].r;
if (l == r)
{
tr[u].k = k, tr[u].b = b;
return;
}
int mid = l + r >> 1;
if (x <= mid) modify (lc, x, k, b);
else modify (rc, x, k, b);
pushup (u);
}
tree query (int u, int x, int y)
{
int l = tr[u].l, r = tr[u].r;
if (x <= l && y >= r) return tr[u];
int mid = l + r >> 1;
tree ans;
if (x <= mid) ans = ans + query (lc, x, y);
if (y > mid) ans = ans + query (rc, x, y);
return ans;
}
signed main ()
{
n = rd (int), m = rd (int);
for (int i = 1; i <= n; i ++ ) k[i] = rd (int), b[i] = rd (int);
build (1, 1, n);
while (m -- )
{
string s; int x, y, z; cin >> s >> x >> y >> z;
if (s == "M") modify (1, x, y, z);
else
{
tree ans = query (1, x, y);
int res = (ans.k * z % mod + ans.b) % mod;
printf ("%lld\n\n", res);
}
}
return 0;
}