P5874 [IOI2015]horses 马 题解
线段树题一遍就A了,写偏题解纪念一下
首先,假设
那么容易得出转移方程 首先,
而
那么转移就很好转移了
由于结果过大,而且取了模会影响比大小,所以我们取对数,乘法变为加法。
询问便直接返回根节点的值
这样写法比许多人写的维护一堆值方便的多,而且代码简洁易懂,目前最优解。
总之,这道题说白了就是道线段树模板题,一定要好好掌握
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 5e5 + 5;
int n, m;
ll X[N], Y[N];
const ll P = 1e9 + 7;
struct {
int l, r;
db sum, mx;
ll mul, ans;
} t[N << 2];
inline void push_up(int p) {
t[p].sum = t[p << 1].sum + t[p << 1 | 1].sum;
t[p].mx = max(t[p << 1].mx, t[p << 1].sum + t[p << 1 | 1].mx);
t[p].mul = t[p << 1].mul * t[p << 1 | 1].mul % P;
if (t[p << 1].mx >= t[p << 1].sum + t[p << 1 | 1].mx)
t[p].ans = t[p << 1].ans;
else t[p].ans = t[p << 1 | 1].ans * t[p << 1].mul % P;
}
void build(int p, int l, int r) {
t[p].l = l, t[p].r = r;
if (l == r) {
t[p].mx = log(1.0 * X[l] * Y[l]);
t[p].sum = log(1.0 * X[l]);
t[p].ans = X[l] % P * Y[l] % P;
t[p].mul = X[l] % P;
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
push_up(p);
}
void change(int p, int x) {
if (t[p].l == t[p].r) {
t[p].mx = log(1.0 * X[x] * Y[x]);
t[p].sum = log(1.0 * X[x]);
t[p].ans = X[x] % P * Y[x] % P;
t[p].mul = X[x] % P;
return;
}
int mid = (t[p].l + t[p].r) >> 1;
if (x <= mid) change(p << 1, x);
else change(p << 1 | 1, x);
push_up(p);
}
main() {
cin >> n;
for (register int i = 1; i <= n; ++i) scanf("%lld", X + i);
for (register int i = 1; i <= n; ++i) scanf("%lld", Y + i);
build(1, 1, n);
printf("%lld\n", t[1].ans);
cin >> m;
while (m--) {
int type, pos;
ll val;
scanf("%d%d%lld", &type, &pos, &val);
if (type == 1) X[pos + 1] = val;
else Y[pos + 1] = val;
change(1, pos + 1);
printf("%lld\n", t[1].ans);
}
}