SPOJ 1557(线段树)
题意大概是说给定一个区间,求最大连续和
完全不会,学习了半天
大概可以理解为一个线段树点更新,区间询问的题目,但是构造和理解起来相对难许多。
这里相同数的处理还是蛮有意思。用pre[i]记录i上一次出现的位置。所以update的时候跳过这个位置就好
用离线算法,将询问区间按r排序后,从第一个至最后一个数依次加入线段树,同时维护四个值:
1.sum 目前区间和
2.maxo 最大区间和
3.lazy 待下传的和
4.lazyo 待下传的最大可更新值
最关键的是pushdown函数
sum、lazy和普通的更新没什么区别,重点在于maxo和lazyo
可以注意到,当lazy<=0时,lazyo是一直为0的。因为如果加入的连续和<=0,maxo不可能被更新
lazy和lazyo不可分别写一个if,因为lazy将更新sum,而sum的更新可能会改变maxo
具体看代码
#include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"cstring" #include"queue" #include"map" #include"vector" #define ll long long #define mems(a,b) memset(a,b,sizeof(a)) #define ls pos<<1 #define rs pos<<1|1 using namespace std; const int MAXN = 100500; const int MAXE = 200500; const int INF = 0x3f3f3f; struct node{ int l,r; ll sum,maxo,lazyo,lazy; }node[MAXN<<2]; struct nod{ int a,b,id; }que[MAXN]; int pre[MAXN*2+10]; ll ans[MAXN],x[MAXN]; bool cmp(nod x,nod y){ return x.b<y.b; } void build(int l,int r,int pos){ node[pos].l=l; node[pos].r=r; node[pos].lazy=node[pos].lazyo=0; node[pos].sum=node[pos].maxo=0; if(l==r) return; int mid=(l+r)>>1;; build(l,mid,pos<<1); build(mid+1,r,pos<<1|1); } void pushup(int pos){ node[pos].sum=max(node[ls].sum,node[rs].sum); node[pos].maxo=max(node[ls].maxo,node[rs].maxo); } void pushdown(int pos){ if(node[pos].lazy||node[pos].lazyo){ node[ls].lazyo=max(node[ls].lazyo,node[ls].lazy+node[pos].lazyo); node[ls].maxo=max(node[ls].maxo,node[ls].sum+node[pos].lazyo); node[ls].lazy+=node[pos].lazy; node[ls].sum+=node[pos].lazy; node[rs].lazyo=max(node[rs].lazyo,node[rs].lazy+node[pos].lazyo); node[rs].maxo=max(node[rs].maxo,node[rs].sum+node[pos].lazyo); node[rs].lazy+=node[pos].lazy; node[rs].sum+=node[pos].lazy; node[pos].lazy=node[pos].lazyo=0; } } void update(int l,int r,int pos,int add){ if(l<=node[pos].l&&node[pos].r<=r){ node[pos].sum+=add; node[pos].lazy+=add; node[pos].lazyo=max(node[pos].lazyo,node[pos].lazy); node[pos].maxo=max(node[pos].sum,node[pos].maxo); return; } pushdown(pos); int mid=(node[pos].l+node[pos].r)>>1; if(l<=mid) update(l,r,ls,add); if(r>mid) update(l,r,rs,add); pushup(pos); } ll query(int l,int r,int pos){ if(l<=node[pos].l&&node[pos].r<=r){ return node[pos].maxo; } ll t=0; pushdown(pos); int mid=(node[pos].l+node[pos].r)>>1; if(l<=mid) t=max(t,query(l,r,ls)); if(r>mid) t=max(t,query(l,r,rs)); return t; } int main(){ int n,q; //freopen("in.txt","r",stdin); while(~scanf("%d",&n)){ for(int i=1;i<=n;i++) scanf("%lld",&x[i]); build(1,n,1); scanf("%d",&q); for(int i=0;i<q;i++){ scanf("%d%d",&que[i].a,&que[i].b); que[i].id=i; } sort(que,que+q,cmp); mems(pre,0); int j=0; for(int i=1;i<=n;i++){ update(pre[MAXN+x[i]]+1,i,1,x[i]); pre[MAXN+x[i]]=i; while(j<q&&que[j].b==i){ ans[que[j].id]=query(que[j].a,que[j].b,1); j++; } } for(int i=0;i<q;i++) printf("%lld\n",ans[i]); } return 0; }