您的位置:首页 > 产品设计 > UI/UE

SPOJ GSS2 Can you answer these queries II

2015-04-09 19:00 459 查看
题意:

给定一个序列和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
, pre[N*2];
struct query {
	int l, r, ans;
}p
;
int id
;
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);
	else
		update(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: