[SPOJ GSS2] Can you answer these queries II [线段树]

来源:互联网 发布:全球地表覆盖数据下载 编辑:程序博客网 时间:2024/04/30 20:06

给定一个序列,查询区间子段去除重复元素的和的最大值。即给x,y,求sum=a[i]+a[i+1]+...+a[j],x<=i<=j<=y的最大的sum,但如果其中a[p]==a[q],i<=p<=q<=j,则计算和的时候a[p]和a[q]只计算一次。

这道题看起来和GSS1相似,但是做法完全不同。

使用数组lx[i]记录a[i]左边第一个等于a[i]的元素的位置+1。

离线处理所有的询问,将其按照右端点排序。

从左向右扫描数列,当扫描到a[i]时,线段树中第j个节点记录从j到i的去除重复元素的和,以及从j到i的区间子段去除重复元素的和的最大值。

即每扫描到一个新的数a[i],令数列b[lx[i]], b[lx[i]+1], ... , b[i]加上a[i],用线段树记录b[i]的区间历史最大值。

#include <cstdio>#include <cstring>#include <map>#include <algorithm>#include <iostream>using namespace std;struct Query {int l,r,i;friend bool operator < (const Query &a,const Query &b) {return a.r<b.r;}};struct SegNode {SegNode *ls,*rs;long long maxv,permaxv,maxlazy,lazy;void down() {if (ls) {ls->maxlazy=max(ls->maxlazy,ls->lazy+maxlazy);ls->lazy+=lazy;}if (rs) {rs->maxlazy=max(rs->maxlazy,rs->lazy+maxlazy);rs->lazy+=lazy;}permaxv=max(permaxv,maxv+maxlazy);maxv+=lazy;lazy=maxlazy=0;}void repair() {ls->down();rs->down();maxv=max(ls->maxv,rs->maxv);permaxv=max(ls->permaxv,rs->permaxv);maxlazy=lazy=0;}};SegNode node[200000];SegNode *root,*an;void print() {for (SegNode *i=node;i!=an;i++) {printf("Node %d:\n",(int)(i-node));printf(" ls:%d rs:%d\n",(int)(i->ls-node),(int)(i->rs-node));printf(" maxv:%lld permaxv:%lld lazy:%lld maxlazy:%lld\n",i->maxv,i->permaxv,i->lazy,i->maxlazy);}printf("\n");}SegNode *maketree(int l,int r) {SegNode *ans=an++;if (l==r) {ans->ls=ans->rs=NULL;} else {int t=(l+r)/2;ans->ls=maketree(l,t);ans->rs=maketree(t+1,r);}ans->maxlazy=ans->lazy=0;ans->maxv=ans->permaxv=0;return ans;}void set(SegNode *from,int l,int r,int ll,int rr,int x) {//printf("%d %d %d %d\n",(int)(from-node),ll,rr,x);from->down();if (l==ll&&r==rr) {from->lazy=x;from->maxlazy=max(x,0);} else {int t=(l+r)/2;if (rr<=t) {set(from->ls,l,t,ll,rr,x);} else if (ll>t) {set(from->rs,t+1,r,ll,rr,x);} else {set(from->ls,l,t,ll,t,x);set(from->rs,t+1,r,t+1,rr,x);}from->repair();}}int get(SegNode *from,int l,int r,int ll,int rr) {from->down();if (l==ll&&r==rr) return from->permaxv;int t=(l+r)/2;if (rr<=t) return get(from->ls,l,t,ll,rr);else if (ll>t) return get(from->rs,t+1,r,ll,rr);else return max(get(from->ls,l,t,ll,t),get(from->rs,t+1,r,t+1,rr));}map<int,int>last;int n;int a[100001];int lx[100001];Query b[100000];int ans[100000];int main() {int i,x;scanf("%d",&n);for (i=1;i<=n;i++) {scanf("%d",&a[i]);lx[i]=last[a[i]]+1;last[a[i]]=i;}an=node;root=maketree(1,n);int q;scanf("%d",&q);for (i=0;i<q;i++) {scanf("%d%d",&b[i].l,&b[i].r);b[i].i=i;}sort(b,b+q);x=1;for (i=0;i<q;i++) {for (;x<=b[i].r;x++) {set(root,1,n,lx[x],x,a[x]);//print();//getchar();}ans[b[i].i]=get(root,1,n,b[i].l,b[i].r);}for (i=0;i<q;i++) {printf("%d\n",ans[i]);}return 0;}


0 0
原创粉丝点击