GSS2 - Can you answer these queries II(线段树)

来源:互联网 发布:马天宇知乎 编辑:程序博客网 时间:2024/05/14 18:11

题意:询问任意区间内,最大连续序列和(相等的值不重复计算),可以不选输出0;

这题可以说一眼看出是线段树了,可是怎么构造确实非常难. 现在假设线段树中的叶子为 s[i]. 每次更新 a[i]的时候,s[1] -s[i]区间内加上a[i];那么

s[1] = a[1] + a[2] + a[3] + ... + a[i];
s[2] = a[2] + a[3] + ... + a[i];

s[3] = a[3] + ... + a[i];

s[i] = a[i];


变形一下就是所求

ss[1] = max( a[1] + a[2]  + ... + a[k1] ) (    k1 <= i );

ss[2] = max( a[2] + a[3] + ...+ a[k2] )  (    k2 <= i );

我们可以求的是以i为右端点的询问,就是 ss[l] ....ss[r]( r == i ) 中的最大值;

到这里还有一个问题需要解决, 重复出现的值不计算??

可以这样:在更新a[i]的时候,更新区间不是1---i 而是pre[a[i]] --- i (pre[a[i]]是a[i]上一次出现的位置);这样就可以解决重复计算问题

线段树结构中:

curmax表示此区间内的最优值

prelazy即将下传的最大值;

lazy为即将下传的总值;

sum表示的区间内 max( s[] );

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<queue>#include<stack>#include<string>#include<map>#include<cmath>using namespace std;#define M 100007struct Tree{int l, r;long long curmax, prelazy, lazy, sum;}tree[M*4];int a[M], n, m, pre[M*2+10];struct Node{int l, r, id;}nde[M];long long ans[M];bool cmp( Node a, Node b ){return a.r < b.r;}void build( int l, int r, int p ){tree[p].l = l; tree[p].r = r;tree[p].curmax = tree[p].prelazy = 0;tree[p].sum = tree[p].lazy = 0;if( l >= r ) return;int mid = (l+r)>>1;build( l, mid, p<<1 );build( mid+1, r, p<<1|1 );}void pushDown( int p ){int ls = p<<1, rs = ls|1;if( tree[p].lazy || tree[p].prelazy ){tree[ls].prelazy = max( tree[ls].prelazy, tree[ls].lazy + tree[p].prelazy );tree[ls].curmax = max( tree[ls].curmax, tree[ls].sum + tree[p].prelazy );tree[ls].lazy += tree[p].lazy; tree[ls].sum += tree[p].lazy;tree[rs].prelazy = max( tree[rs].prelazy, tree[rs].lazy + tree[p].prelazy );tree[rs].curmax = max( tree[rs].curmax, tree[rs].sum + tree[p].prelazy );tree[rs].lazy += tree[p].lazy; tree[rs].sum += tree[p].lazy;tree[p].lazy = 0; tree[p].prelazy = 0;}}void pushUp( int p ){tree[p].sum = max( tree[p<<1].sum, tree[p<<1|1].sum );tree[p].curmax = max( tree[p<<1].curmax, tree[p<<1|1].curmax );}void insert( int l, int r, int p, long long x ){if( l <= tree[p].l && r >= tree[p].r ){tree[p].sum += x;tree[p].lazy += x;tree[p].prelazy = max( tree[p].prelazy, tree[p].lazy );tree[p].curmax = max( tree[p].curmax, tree[p].sum );return;}if( l > tree[p].r || r < tree[p].l ) return;pushDown( p );insert( l, r, p<<1, x );insert( l, r, p<<1|1, x );pushUp( p );}long long query( int l, int r, int p ){if( l <= tree[p].l && r >= tree[p].r ){return tree[p].curmax;}if( l > tree[p].r || r < tree[p].l ) return 0;pushDown( p );return max( query(l, r, p<<1), query(l, r, p<<1|1) );//pushUp( p );}int main(){while( scanf( "%d", &n ) == 1 ){for( int i = 1; i <= n; i++ )scanf( "%d", a+i );scanf( "%d", &m );build( 1, n, 1 );for( int i = 0; i < m; i++ ){scanf( "%d%d", &nde[i].l, &nde[i].r );nde[i].id = i;}sort( nde, nde + m, cmp );memset( pre, 0, sizeof(pre) );int j = 0;for( int i = 1; i <= n; i++ ){insert( pre[a[i]+M]+1, i, 1, a[i] );pre[a[i]+M] = i;while( j < m && nde[j].r == i ){ans[nde[j].id] = query( nde[j].l, nde[j].r, 1 );j++;}}for( int i = 0; i < m; i++ )cout<<ans[i]<<endl;}}


0 0
原创粉丝点击