求区间最大子段和,而且不能有重复元素的
为了避免重复元素,我们用扫描线
把所有询问离线下来,按照r升序排序
对于一个元素a[i],每次扫描到,就在pre[a[i]]+1~i 加入元素 a[i],然后查询查询区间的历史区间最大值,然后这个历史区间最大值就是[l,l+1],[l,l+2]***[l,r]的
最大子段和就是在[l],[l+1]
[r]这些左端点的区间的最大值里面挑选最大值
我们查询[l,r]的历史区间最值就是这个max([l,l],[l,l + 1],[l,l + 2].....[l,r])里面的历史区间最值,就是[l,.........] [l + 1.......] [l + 2.............] [r,......]的最大值
可能就是这样吧。
const int N = 1e5 + 79;
int a[N], q, n;
struct question {
int l, r, id;
inline bool operator <(const question &rhs) {
return r < rhs.r;
}
} t[N];
int pre[N * 2];
struct SegmentTree {
lxl mx[N << 1], Hismx[N << 1], tag[N << 1], Histag[N << 1];
int lc[N << 1], rc[N << 1], rt, cnt;
inline void pushup(int p) {
mx[p] = max(mx[lc[p]], mx[rc[p]]);
Hismx[p] = max(Hismx[lc[p]], Hismx[rc[p]]);
tag[p] = Histag[p] = 0;
}
inline void pushdown(int p) {
if(tag[p] == 0 && Histag[p] == 0) return ;
if(!lc[p]) lc[p] = ++cnt;
Hismx[lc[p]] = max(Hismx[lc[p]], mx[lc[p]] + Histag[p]);
Histag[lc[p]] = max(Histag[lc[p]], tag[lc[p]] + Histag[p]);
mx[lc[p]] += tag[p];
tag[lc[p]] += tag[p];
if(!rc[p]) rc[p] = ++cnt;
Hismx[rc[p]] = max(Hismx[rc[p]], mx[rc[p]] + Histag[p]);
Histag[rc[p]] = max(Histag[rc[p]], tag[rc[p]] + Histag[p]);
mx[rc[p]] += tag[p];
tag[rc[p]] += tag[p];
tag[p] = Histag[p] = 0;
}
inline void add(int &p, int L, int R, int ll, int rr, lxl val) {
if(!p) p = ++cnt;
if(ll <= L && rr >= R) {
mx[p] += val;
Hismx[p] = max(Hismx[p], mx[p]);
tag[p] += val;
Histag[p] = max(Histag[p], tag[p]);
return ;
}
pushdown(p);
int mid(L + R >> 1);
if(ll <= mid) add(lc[p], L, mid, ll, rr, val);
if(rr > mid) add(rc[p], mid + 1, R, ll, rr, val);
pushup(p);
}
inline lxl query(int &p, int L, int R, int ll, int rr) {
if(!p) return -1e18;
if(ll <= L && rr >= R) {
return Hismx[p];
}
pushdown(p);
int mid(L + R >> 1);
lxl ans = -1e18;
if(ll <= mid) ans = max(ans, query(lc[p], L, mid, ll, rr));
if(rr > mid) ans = max(ans, query(rc[p], mid + 1, R, ll, rr));
return ans;
}
} S;
lxl ans[N];
int main() {
read(n);
rep(i, 1, n) {
read(a[i]);
}
read(q);
rep(i, 1, q) {
read(t[i].l);
read(t[i].r);
t[i].id = i;
}
std::sort(t + 1, t + q + 1);
int j(1);
rep(i, 1, n) {
S.add(S.rt, 1, n, pre[a[i] + 100000] + 1, i, a[i]);
pre[a[i] + 100000] = i;
while(t[j].r == i && j <= q) {
ans[t[j].id] = S.query(S.rt, 1, n, t[j].l, t[j].r);
++j;
}
}
rep(i, 1, q) {
out(ans[i], '\n');
}
return 0;
}