/*
题意:求一个区间内的最大的子序列的和:要求必须子序列中相邻的数下标奇偶性不同。
维护区间内的
开始奇结束偶
开始奇结束奇
开始偶结束奇
开始偶结束偶
*/
# include <stdio.h>
# include <algorithm>
# include <string.h>
using namespace std;
# define lson l,m,rt<<1
# define rson m+1,r,rt<<1|1
# define N 100010
# define inf 0x3f3f3f3f
__int64 a[N];
struct node
{
__int64 jj;
__int64 jo;
__int64 oj;
__int64 oo;
};
node p[N*4];
node big(node a,node b)
{
node c;
c.jj=max(a.jj,b.jj);
c.jj=max(c.jj,a.jj+b.oj);
c.jj=max(c.jj,a.jo+b.jj);
c.oj=max(a.oj,b.oj);
c.oj=max(c.oj,a.oj+b.oj);
c.oj=max(c.oj,a.oo+b.jj);
c.jo=max(a.jo,b.jo);
c.jo=max(c.jo,a.jj+b.oo);
c.jo=max(c.jo,a.jo+b.jo);
c.oo=max(a.oo,b.oo);
c.oo=max(c.oo,a.oj+b.oo);
c.oo=max(c.oo,a.oo+b.jo);
return c;
}
void PushUP(int rt)
{
p[rt]=big(p[rt<<1],p[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
if(l%2)//奇
{
p[rt].jj=a[l];
p[rt].jo=-inf;
p[rt].oj=-inf;;
p[rt].oo=-inf;
}
else//偶
{
p[rt].jj=-inf;
p[rt].jo=-inf;
p[rt].oj=-inf;
p[rt].oo=a[l];
}
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUP(rt);
}
void update(int pos,__int64 val,int l,int r,int rt)
{
if(l==r)
{
if(pos%2)
{
p[rt].jj=val;
}
else
{
p[rt].oo=val;
}
return ;
}
int m=(l+r)>>1;
if(pos<=m)
update(pos,val,lson);
else
update(pos,val,rson);
PushUP(rt);
}
node query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return p[rt];
int m=(l+r)>>1;
if(m>=L&&m<R)
return big(query(L,R,lson),query(L,R,rson));
if(L<=m)
{
query(L,R,lson);
}
if(m<R)
{
query(L,R,rson);
}
}
int main()
{
int t,n,m,i,op;
__int64 L,R;
while(~scanf("%d",&t))
{
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++)
scanf("%I64d",&a[i]);
build(1,n,1);
while(m--)
{
scanf("%d%I64d%I64d",&op,&L,&R);
if(op==1)
{
update(L,R,1,n,1);//单点更新
}
else
{
node ans=query(L,R,1,n,1);
printf("%I64d\n",max(max(ans.jj,ans.jo),max(ans.oj,ans.oo)));
}
}
}
}
return 0;
}
hdu 5316 Magician (线段树)
最新推荐文章于 2020-07-07 19:40:15 发布