HDU 5316 Magician(线段树 区间合并)

来源:互联网 发布:5g网络有多快 编辑:程序博客网 时间:2024/04/29 18:08

题意:给你n(n<=10^5)个数ai(-10^9<=ai<=10^9)。要求从这里面取出它的序列,这些序列满足下标奇偶相间,求某段区间的这种序列的最大和值。

分析:最初没读懂题意。。。。 一看数据范围和查询方式,肯定和线段树相关,问题的要求又有点像DP。分析知道,其实就是求线段树的区间合并问题,取出的序列只可能是以奇数开头奇数结尾,奇数开头偶数结尾,偶数开头偶数结尾,偶数开头奇数结尾。用jj,jo,oo,oj表示。当合并的适合考虑这四种情况就是可以了。

jj=max(l.jj ,r.jj,  l.jj+r.oj,   l.jo+r.jo);其他依次类推

#include <iostream>#include <stdio.h>#include <math.h>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <string>#include <string.h>#include <map>#include <set>using namespace std;#define maxn 200005#define inff 0x7FFFFFFFFFFFFFFFtypedef __int64 LL;LL a[maxn];int n,m; LL max(LL x,LL y){    return x>y?x:y;} LL max(LL x,LL y,LL z,LL w){    return max(max(x,y),max(z,w));}struct node{    int l,r;    LL oo,jj,jo,oj;}tr[maxn<<2];inline LL add(LL x,LL y){    if(x==-inff||y==-inff)return -inff;    else return x+y;}void pushup(int id){  tr[id].jj=max(add(tr[id*2].jo,tr[id*2+1].jj),add(tr[id*2].jj,tr[id*2+1].oj),tr[id*2].jj,tr[id*2+1].jj);  tr[id].oo=max(add(tr[id*2].oj,tr[id*2+1].oo),add(tr[id*2].oo,tr[id*2+1].jo),tr[id*2].oo,tr[id*2+1].oo);  tr[id].jo=max(add(tr[id*2].jj,tr[id*2+1].oo),add(tr[id*2].jo,tr[id*2+1].jo),tr[id*2].jo,tr[id*2+1].jo);  tr[id].oj=max(add(tr[id*2].oo,tr[id*2+1].jj),add(tr[id*2].oj,tr[id*2+1].oj),tr[id*2].oj,tr[id*2+1].oj);}void build(int id,int l,int r){    tr[id].l=l;    tr[id].r=r;    tr[id].jj=tr[id].oo=-inff;     tr[id].oj=tr[id].jo=-inff;    if(l==r)    {        if(l%2!=0)        {            tr[id].jj=a[l];            tr[id].oo=tr[id].jo=tr[id].oj=-inff;        }        else        {            tr[id].oo=a[l];            tr[id].jj=tr[id].jo=tr[id].oj=-inff;        }    }    else    {        int mid=(l+r)/2;        build(id*2,l,mid);        build(id*2+1,mid+1,r);        pushup(id);    }}void update(int id,int pos,LL val){    if(tr[id].l==tr[id].r)    {        if(tr[id].l%2!=0)        {            tr[id].jj=val;            tr[id].oo=tr[id].jo=tr[id].oj=-inff;        }        else        {            tr[id].oo=val;            tr[id].jj=tr[id].jo=tr[id].oj=-inff;        }    }    else    {        int mid=(tr[id].l+tr[id].r)/2;        if(pos<=mid)update(id*2,pos,val);        else update(id*2+1,pos,val);        pushup(id);    }}node query(int id,int l,int r){    if(l<=tr[id].l&&tr[id].r<=r)    {        return tr[id];    }    else    {        int mid=(tr[id].l+tr[id].r)/2;        if(r<=mid)return query(id*2,l,r);        else if(l>mid)return query(id*2+1,l,r);        else        {            node a=query(id*2,l,r);            node b=query(id*2+1,l,r);            node c;            c.jj=max(a.jj,b.jj,add(a.jo,b.jj),add(a.jj,b.oj));            c.oo=max(a.oo,b.oo,add(a.oj,b.oo),add(a.oo,b.jo));            c.jo=max(a.jo,b.jo,add(a.jj,b.oo),add(a.jo,b.jo));            c.oj=max(a.oj,b.oj,add(a.oo,b.jj),add(a.oj,b.oj));            return c;        }    }}int main(){    int t,i;    //cout<<inff<<endl;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        for(i=1;i<=n;i++)        {            scanf("%I64d",&a[i]);        }        build(1,1,n);        //cout<<tr[1].jj<<" "<<tr[1].oo<<" "<<tr[1].oj<<endl;        for(i=1;i<=m;i++)        {            int pos;            LL val;            int c,l,r;            scanf("%d",&c);            if(c==1)            {                scanf("%d%I64d",&pos,&val);                update(1,pos,val);            }            else            {                scanf("%d%d",&l,&r);                node ans=query(1,l,r);                printf("%I64d\n",max(ans.jj,ans.jo,ans.oo,ans.oj));            }        }    }    return 0;}


0 0