[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
- [SPOJ GSS2] Can you answer these queries II [线段树]
- 【线段树】spoj GSS2 Can you answer these queries II
- GSS2 - Can you answer these queries II(线段树)
- SPOJ 1557 Can you answer these queries II(GSS2 线段树)
- spoj 1557 Can you answer these queries II (gss2)线段树
- BZOJ 2482 || SPOJ GSS2 Can you answer these queries II(线段树 离线 后缀和)
- SPOJ GSS2 Can you answer these queries II
- spoj 1557. Can you answer these queries II(线段树)
- 【SPOJ】1557 Can you answer these queries II 线段树
- [SPOJ1557][GSS2][线段树]Can you answer these queries II[好题]
- SPOJ/GSS3:Can you answer these queries III(线段树)
- spoj 1043. Can you answer these queries I (线段树)
- spoj 1716. Can you answer these queries III(线段树)
- spoj 2713. Can you answer these queries IV(线段树)
- spoj 2916. Can you answer these queries V(线段树)
- SPOJ GSS3 Can you answer these queries III (线段树)
- SPOJ GSS4 Can you answer these queries IV (线段树)
- 【SPOJ】Can you answer these queries I【线段树】
- JAVA语言的三种技术架构
- CF#252 (Div. 2) A.
- 【TOJ 2433】Word Rings【SPFA+二分】
- Java语言的特点:跨平台性
- 个人面试总结(共勉)
- [SPOJ GSS2] Can you answer these queries II [线段树]
- 数据结构之哈夫曼树
- hdu2201 熊猫阿波的故事
- 100AC
- 黑马程序员-----初识OC(三)
- C#中get和set不带参数
- JTAG各类接口针脚定义及含义
- 验证过的模拟登录的方式,结合scrapy和selenium(phantom)
- Java语言的环境搭建