rt,如果某道题目的 ans 可能是负数但是我的李超树只会执行
PIII query(int p, int l, int r, int d) {
if (r < d || d < l) return {0, 0};//<---这个
···
}
并且有提前 insert 一条很小的线段,不确定是不是这么 insert 的。
题目是 Codechef 的 The street。
in
10 10
3 5
1 3 8 3 1
3 5
1 5 10 -8 2
3 5
3 10
2 1 10 0 1
3 6
2 5 7 2 1
3 6
out
NA
7
7
-38\\<---就是这个负数也会输出 NA
11
14
所以说是啥问题,怎么解决?
附代码(建议无视 namespace SegmentTree 里的内容)
#include <bits/stdc++.h>
#define rep(i, j, k) for(int i = j; i <= k; ++i)
#define pre(i, j, k) for(int i = j; i >= k; --i)
#define pb push_back
#define PII pair<int, int>
#define fir first
#define sec second
#define int long long
#define y1 li_junyi
#define ls (p << 1)
#define rs (p << 1 | 1)
using namespace std;
const double eps = 1e-10;
const int N = 3e5 + 5;
const int M = 3e5;
typedef pair<double, int> PIII;
namespace Shab_Li_Chao_SegmentTree {
int cmp(double x, double y) {
if(x - y > eps) return 1;
if(y - x > eps) return -1;
return 0;
}
struct line {
double k, b;
#define k(i) P[i].k
#define b(i) P[i].b
} P[N];
int s[N], cnt;
void init() {
int p = ++cnt;
k(p) = 0, b(p) = -1000000000000;
}
double calc(int p, int d) {
return b(p) + k(p) * d;
}
void Add(double x0, double y0, double x1, double y1) {
int p = ++cnt;
if(x0 == x1) k(p) = 0, b(p) = max(y0, y1);
else k(p) = 1.0 * (y1 - y0) / (x1 - x0), b(p) = y0 - k(p) * x0;
}
void Upd(int p, int l, int r, int u) {
int &v = s[p], mid = l + r >> 1;
int bmid = cmp(calc(u, mid), calc(v, mid));
if (bmid == 1 || (!bmid && u < v)) swap(u, v);
int bl = cmp(calc(u, l), calc(v, l)), br = cmp(calc(u, r), calc(v, r));
if (bl == 1 || (!bl && u < v)) Upd(p << 1, l, mid, u);
if (br == 1 || (!br && u < v)) Upd(p << 1 | 1, mid + 1, r, u);
}
void update(int p, int ql, int qr, int l, int r, int u) {
if (l <= ql && qr <= r) {
Upd(p, ql, qr, u);
return;
}
int mid = ql + qr >> 1;
if (l <= mid) update(p << 1, ql, mid, l, r, u);
if (mid < r) update(p << 1 | 1, mid + 1, qr, l, r, u);
}
PIII pmx(PIII x, PIII y) {
if (cmp(x.first, y.first) == -1)
return y;
if (cmp(x.first, y.first) == 1)
return x;
return x.second < y.second ? x : y;
}
PIII query(int p, int l, int r, int d) {
if (r < d || d < l) return {0, 0};
int mid = l + r >> 1;
double res = calc(s[p], d);
if (l == r) return {res, s[p]};
return pmx({res, s[p]}, pmx(query(p << 1, l, mid, d),
query(p << 1 | 1, mid + 1, r, d)));
}
}
using namespace Shab_Li_Chao_SegmentTree;
namespace SegmentTree {
struct node {
int l, r, sum, add;
#define l(p) t[p].l
#define r(p) t[p].r
#define sum(p) t[p].sum
#define add(p) t[p].add
} t[N << 2];
void pushup(int p) {
sum(p) = sum(ls) + sum(rs);
}
void pushdown(int p) {
if(add(p)) {
add(ls) += add(p), add(rs) += add(p);
sum(ls) += (r(ls) - l(ls) + 1) * add(p), sum(rs) += (r(rs) - l(rs) + 1) * add(p);
add(p) = 0;
}
}
void build(int p, int l, int r) {
l(p) = l, r(p) = r;
if(l == r) return;
int mid = l + r >> 1;
build(ls, l, mid), build(rs, mid + 1, r);
pushup(p);
}
void upd(int p, int l, int r, int x) {
if(l <= l(p) && r(p) <= r) return sum(p) += (r(p) - l(p) + 1) * x, add(p) += x, void();
pushdown(p);
int mid = l(p) + r(p) >> 1;
if(l <= mid) upd(ls, l, r, x);
if(r > mid) upd(rs, l, r, x);
pushup(p);
}
int ask(int p, int l, int r) {
if(l <= l(p) && r(p) <= r) return sum(p);
pushdown(p);
int mid = l(p) + r(p) >> 1, val = 0;
if(l <= mid) val += ask(ls, l, r);
if(r > mid) val += ask(rs, l, r);
return val;
}
}
using namespace SegmentTree;
signed main() {
ios::sync_with_stdio(0);
cin.tie(nullptr), cout.tie(nullptr);
int ans = 0, q, n;
cin >> n >> q;
build(1, 1, n); init();
while (q--) {
int op;
cin >> op;
if (op == 1) {
int u, v, a, b;
cin >> u >> v >> a >> b;//a公差b首项
double k = a;
double x0 = u, y0 = k * 1.0 * (x0 - u) + b, x1 = v, y1 = k * (x1 - u) + b;
Add(x0, y0, x1, y1);
update(1, 1, n, x0, x1, cnt);
} else if(op == 3) {
int x;
cin >> x;
int Q1 = query(1, 1, n, x).first,
Q2 = ask(1, 1, x);
if(!Q1) cout << "NA\n";
else cout << Q1 + Q2 << '\n';
} else {
int u, v, a, b;
cin >> u >> v >> a >> b;
upd(1, u, u, b);
if(u + 1 <= v) upd(1, u + 1, v, a);
if(v + 1 <= n) upd(1, v + 1, v + 1, -(b + a * (v - u)));
}
}
}