SPOJ - GSS2 Can you answer these queries II

题意:

给定一个长为 n 的数组 a,有 q 次询问,每次询问区间 [ L, R ] 的最大子段和(相同元素只计一次)。(n, q, a i a_i <= 1e5)

链接:

https://vjudge.net/problem/SPOJ-GSS2

解题思路:

考虑离线,每次遇到右端点时统计答案。对于当前元素 a[ i ],只对 last[ a[ i ] ] + 1 到 i 这一段增加 a[ i ],则对于询问 [ l, i ],答案就是区间内的历史最值。
线段树维护历史最值,记当前最值为 mx,历史最值为 pmx,当前标记为 add,历史最大标记为 padd(add 下推前的最值),则历史最值的 pushdown 操作为:
p a d d [ s o n ] = m a x ( p a d d [ s o n ] , a d d [ s o n ] + p a d d [ r t ] ) ; padd[son] = max(padd[son], add[son] + padd[rt]);
p m x [ s o n ] = m a x ( p m x [ s o n ] , m x [ s o n ] + p a d d [ r t ] ) ; pmx[son] = max(pmx[son], mx[son] + padd[rt]);
当前最值及标记照常维护即可。

参考代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define sz(a) ((int)a.size())
#define mem(a, b) memset(a, b, sizeof a)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int maxm = 2e6 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

vector<pii> G[maxn];
ll mx[maxn << 2], add[maxn << 2];
ll pmx[maxn << 2], padd[maxn << 2];
int a[maxn], ri[maxn], last[maxn << 1];
ll ans[maxn];
int n, q;

void build(int l, int r, int rt){

	padd[rt] = add[rt] = pmx[rt] = mx[rt] = 0;
	if(l == r) return;
	int mid = gmid;
	build(l, mid, lson);
	build(mid + 1, r, rson);
}

void pushUp(int rt){

	pmx[rt] = max(pmx[lson], pmx[rson]);
	mx[rt] = max(mx[lson], mx[rson]);
}

void pushDown(int rt){

	padd[lson] = max(padd[lson], add[lson] + padd[rt]);
	padd[rson] = max(padd[rson], add[rson] + padd[rt]);
	pmx[lson] = max(pmx[lson], mx[lson] + padd[rt]);
	pmx[rson] = max(pmx[rson], mx[rson] + padd[rt]);
	add[lson] += add[rt], add[rson] += add[rt];
	mx[lson] += add[rt], mx[rson] += add[rt];
	padd[rt] = add[rt] = 0;
}

void update(int l, int r, int rt, int L, int R, int val){

	if(l >= L && r <= R){

		padd[rt] = max(padd[rt], add[rt] += val);
		pmx[rt] = max(pmx[rt], mx[rt] += val);
		return;
	}
	int mid = gmid;
	pushDown(rt);
	if(L <= mid) update(l, mid, lson, L, R, val);
	if(R > mid) update(mid + 1, r, rson, L, R, val);
	pushUp(rt);
}

ll query(int l, int r, int rt, int L, int R){

	if(l >= L && r <= R) return pmx[rt];
	int mid = gmid; ll ret = 0;
	pushDown(rt);
	if(L <= mid) ret = max(ret, query(l, mid, lson, L, R));
	if(R > mid) ret = max(ret, query(mid + 1, r, rson, L, R));
	return ret;
}

int main(){

//	ios::sync_with_stdio(0); cin.tie(0);
	while(scanf("%d", &n) != EOF){

		for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
		scanf("%d", &q);
		for(int i = 1; i <= q; ++i){

			int l; scanf("%d%d", &l, &ri[i]);
			G[ri[i]].pb({l, i});
		}
		build(1, n, 1);
		for(int i = 1; i <= n; ++i){

			update(1, n, 1, last[a[i] + maxn] + 1, i, a[i]);
			last[a[i] + maxn] = i;
			for(int j = 0; j < sz(G[i]); ++j){

				int l = G[i][j].first, p = G[i][j].second;
				ans[p] = query(1, n, 1, l, i);
			}
		}
		for(int i = 1; i <= q; ++i) printf("%lld\n", ans[i]);
		for(int i = 1; i <= n; ++i) last[a[i] + maxn] = 0;
		for(int i = 1; i <= q; ++i) G[ri[i]].clear();
	}
	return 0;
}
发布了55 篇原创文章 · 获赞 0 · 访问量 1276

猜你喜欢

转载自blog.csdn.net/weixin_44059127/article/details/101210805
今日推荐