SPOJ GSS2 Can you answer these queries II

来源:互联网 发布:店铺收银软件 编辑:程序博客网 时间:2024/04/30 07:51

题意:

给定一个序列和m个询问, 要求求出一个区间内最大连续子段和, 并且相同的数只能算一次。

思路:

把询问离线, 按右端点排序,从小到大扫描询问, 假设当前询问的右端点是r, 用线段树维护4个值:

mx_s: 左端点为ll,右端点在[l,r]的最大连续子段和(也就是最优的情况)。

s:左端点为ll, 到r的区间和。

mx_add: 区间的最优懒惰标记。

add: 区间的所有懒惰标记。

更新第i个数时候, 把pre[a[i]] + 1 ~ i都加上a[i]。

查询的时候就是l~r的mx_s

重点在push_up和push_down...

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <cmath>#include <queue>#include <iomanip>#include <map>#include <set>#include <algorithm>using namespace std;#define N 100020#define mod 1000000007#define mxe 2000020#define MP make_pair#define PB push_back#define LL long long#define ULL unsigned LL#define inf 0x3f3f3f3f#define ls (i << 1)#define rs (ls | 1)#define md ((ll + rr) >> 1)#define lson ll, md, ls#define rson md + 1, rr, rs#pragma comment(linker, "/STACK:1024000000,1024000000")int n, m;int s[N<<2], mx_s[N<<2], add[N<<2], mx_add[N<<2];int a[N], pre[N*2];struct query {int l, r, ans;}p[N];int id[N];bool cmp(int i, int j) {return p[i].r < p[j].r;}void add_val(int i, int v) {add[i] += v;mx_add[i] = max(mx_add[i], add[i]);s[i] += v;mx_s[i] = max(mx_s[i], s[i]);}void push_down(int i) {mx_add[ls] = max(mx_add[ls], add[ls] + mx_add[i]);add[ls] += add[i];mx_s[ls] = max(mx_s[ls], s[ls] + mx_add[i]);s[ls] += add[i];mx_add[rs] = max(mx_add[rs], add[rs] + mx_add[i]);add[rs] += add[i];mx_s[rs] = max(mx_s[rs], s[rs] + mx_add[i]);s[rs] += add[i];add[i] = mx_add[i] = 0;}void push_up(int i) {mx_s[i] = max(mx_s[ls], mx_s[rs]);s[i] = max(s[ls], s[rs]);}void update(int l, int r, int v, int ll, int rr, int i) {if(ll == l && rr == r) {add_val(i, v);return;}push_down(i);if(r <= md) update(l, r, v, lson);else if(l > md) update(l, r, v, rson);elseupdate(l, md, v, lson), update(md + 1, r, v, rson);push_up(i);}int query(int l, int r, int ll, int rr, int i) {if(ll == l && rr == r) return mx_s[i];push_down(i);if(r <= md) return query(l, r, lson);if(l > md) return query(l, r, rson);return max(query(l, md, lson), query(md + 1, r, rson));}int main() {//freopen("tt.txt", "r", stdin);while(scanf("%d", &n) != EOF) {for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);scanf("%d", &m);for(int i = 1; i <= m; ++i) {scanf("%d%d", &p[i].l, &p[i].r);id[i] = i;}sort(id + 1, id + m + 1, cmp);memset(s, 0, sizeof s);memset(mx_s, 0, sizeof mx_s);memset(add, 0, sizeof add);memset(mx_add, 0, sizeof mx_add);memset(pre, 0, sizeof pre);int j = 1;for(int i = 1; i <= m; ++i) {int u = id[i];while(j <= n && j <= p[u].r) {update(pre[a[j]+N] + 1, j, a[j], 1, n, 1);pre[a[j]+N] = j;++j;}p[u].ans = query(p[u].l, p[u].r, 1, n, 1);}for(int i = 1; i <= m; ++i)printf("%d\n", p[i].ans);}return 0;}


0 0