赛时直接用的long long,30pts。把大于2^30的数限定为2^30+1是45pts,多了性质A的分。直接改成__int128_t是85pts。
上述的第一种改良方法应该是可行的(见人AC了),但不知道漏了什么。
代码(大样例过了):
#include <iostream>
#include <cstdio>
#define int long long
namespace io {
inline int read() {
char ch = getchar(); int flag = 1, res = 0;
while (ch < '0' || ch > '9') { if (ch == '-') flag = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { res = (res << 1) + (res << 3) + ch - '0'; ch = getchar(); }
return flag * res;
}
inline void write(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace std;
using namespace io;
const int N = 200010, M = (1 << 30) + 1;
int n, q;
int a[N];
class SegTree {
private:
struct Node {
int sum;
int maxl, maxr, maxn;
int minl, minr, minn; // 定义...
} c[N << 2];
void calc(Node& rt, Node lc, Node rc) {
rt.sum = lc.sum * rc.sum;
rt.maxl = max(lc.maxl, max(lc.sum * rc.maxl, lc.sum * rc.minl));
rt.maxr = max(rc.maxr, max(rc.sum * lc.maxr, rc.sum * lc.minr));
rt.maxn = max(max(lc.maxn, rc.maxn), max(lc.maxr * rc.maxl, lc.minr * rc.minl));
rt.minl = min(lc.minl, min(lc.sum * rc.minl, lc.sum * rc.maxl));
rt.minr = min(rc.minr, min(rc.sum * lc.minr, rc.sum * lc.maxr));
rt.minn = min(min(lc.minn, rc.minn), min(lc.minr * rc.maxl, lc.maxr * rc.minl));
rt.sum = min(rt.sum, M);
rt.maxl = min(rt.maxl, M);
rt.maxr = min(rt.maxr, M);
rt.maxn = min(rt.maxn, M);
rt.minl = max(rt.minl, -M);
rt.minr = max(rt.minr, -M);
rt.minn = max(rt.minn, -M); // 这里是我对第一中改良方法的处理
}
void update(Node& res, Node val) {
if (res.sum == 0) {
res = val;
return;
}
Node tmp = res;
calc(res, tmp, val);
}
public:
void buildTree(int p, int l, int r) {
if (l == r) {
if (a[l] > 0)
c[p] = (Node){a[l], a[l], a[l], a[l], 1, 1, 1};
else
c[p] = (Node){a[l], 1, 1, 1, a[l], a[l], a[l]};
return;
}
int mid = l + (r - l >> 1);
buildTree(p << 1, l, mid);
buildTree(p << 1 | 1, mid + 1, r);
calc(c[p], c[p << 1], c[p << 1 | 1]);
}
void change(int p, int l, int r, int x, int y) {
if (l == r) {
if (y > 0)
c[p] = (Node){y, y, y, y, 1, 1, 1};
else
c[p] = (Node){y, 1, 1, 1, y, y, y};
return;
}
int mid = l + (r - l >> 1);
if (x <= mid)
change(p << 1, l, mid, x, y);
else
change(p << 1 | 1, mid + 1, r, x, y);
calc(c[p], c[p << 1], c[p << 1 | 1]);
}
Node query(int p, int l, int r, int s, int t) {
if (s <= l && r <= t)
return c[p];
int mid = l + (r - l >> 1);
Node res = (Node){0, 0, 0, 0, 0, 0, 0};
if (s <= mid)
update(res, query(p << 1, l, mid, s, t));
if (t > mid)
update(res, query(p << 1 | 1, mid + 1, r, s, t));
return res;
}
} st;
signed main() {
// freopen("T1ex2.in", "r", stdin);
// freopen("a.out", "w", stdout);
n = read(), q = read();
for (int i = 1; i <= n; i++)
a[i] = read();
st.buildTree(1, 1, n);
int opt, x, y;
while (q--) {
opt = read(), x = read(), y = read();
if (opt == 1) {
st.change(1, 1, n, x, y);
} else {
int ans = st.query(1, 1, n, x, y).maxn;
if (ans == M)
puts("Too large");
else
write(ans), puts("");
}
}
// puts(""), system("pause");
return 0;
}