题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5316
题意:给出一个大小为n的区间,2种操作,更新某一个点的值,或者查询[l,r]区间的“最大值序列”(要求该序列的下标奇偶相间)
思路:线段树的单点更新和区间合并可以实现题目要求,我们维护4个数据就好,查询的比较特殊
(1).区间里最大的以奇数开头和以奇数结尾的序列
(2).区间里最大的以偶数开头和以偶数结尾的序列
(3).区间里最大的以奇数开头和以偶数结尾的序列
(4).区间里最大的以偶数开头和以奇数结尾的序列
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
#define maxn 100030
#define inf 100000000030
#define data tree
using namespace std;
struct Tree
{
int l,r;
LL eo,ee,oo,oe;
}tree[maxn*5];
LL s[maxn];
void pushup(int root)
{
tree[root].ee=max(tree[root<<1].eo+tree[root<<1|1].ee,tree[root<<1].ee+tree[root<<1|1].oe);
tree[root].ee=max(tree[root].ee,tree[root<<1].ee);
tree[root].ee=max(tree[root].ee,tree[root<<1|1].ee);
tree[root].oo=max(tree[root<<1].oe+tree[root<<1|1].oo,tree[root<<1].oo+tree[root<<1|1].eo);
tree[root].oo=max(tree[root].oo,tree[root<<1].oo);
tree[root].oo=max(tree[root].oo,tree[root<<1|1].oo);
tree[root].eo=max(tree[root<<1].eo+tree[root<<1|1].eo,tree[root<<1].ee+tree[root<<1|1].oo);
tree[root].eo=max(tree[root].eo,tree[root<<1].eo);
tree[root].eo=max(tree[root].eo,tree[root<<1|1].eo);
tree[root].oe=max(tree[root<<1].oe+tree[root<<1|1].oe,tree[root<<1].oo+tree[root<<1|1].ee);
tree[root].oe=max(tree[root].oe,tree[root<<1].oe);
tree[root].oe=max(tree[root].oe,tree[root<<1|1].oe);
}
void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
if (tree[root].l==tree[root].r)
{
if (l%2==0)
tree[root].oo=s[l];
else
tree[root].ee=s[l];
return;
}
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
pushup(root);
}
void update(int root,int p,int val)
{
if (tree[root].l==tree[root].r)
{
if (tree[root].l%2==0)
tree[root].oo=val;
else
tree[root].ee=val;
return;
}
int mid=(tree[root].l+tree[root].r)>>1;
if (mid>=p) update(root<<1,p,val);
else if (mid<p) update(root<<1|1,p,val);
pushup(root);
}
Tree query(int root,int l,int r)
{
//cout<<root<<endl;
if (tree[root].l==l && tree[root].r==r)
{
return tree[root];
}
int mid=(tree[root].l+tree[root].r)>>1;
if (mid>=r)
return query(root<<1,l,r);
else if (mid<l)
return query(root<<1|1,l,r);
else
{
Tree tmp1=query(root<<1,l,mid);
Tree tmp2=query(root<<1|1,mid+1,r);
Tree tmp3;
tmp3.ee=max(tmp1.eo+tmp2.ee,tmp1.ee+tmp2.oe);
tmp3.ee=max(tmp3.ee,tmp1.ee);
tmp3.ee=max(tmp3.ee,tmp2.ee);
tmp3.oo=max(tmp1.oe+tmp2.oo,tmp1.oo+tmp2.eo);
tmp3.oo=max(tmp3.oo,tmp1.oo);
tmp3.oo=max(tmp3.oo,tmp2.oo);
tmp3.eo=max(tmp1.eo+tmp2.eo,tmp1.ee+tmp2.oo);
tmp3.eo=max(tmp3.eo,tmp1.eo);
tmp3.eo=max(tmp3.eo,tmp2.eo);
tmp3.oe=max(tmp1.oe+tmp2.oe,tmp1.oo+tmp2.ee);
tmp3.oe=max(tmp3.oe,tmp1.oe);
tmp3.oe=max(tmp3.oe,tmp2.oe);
return tmp3;
}
}
int main()
{
int t,n,m;
scanf("%d",&t);
while (t--)
{
memset(tree,-inf,sizeof(tree));
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%I64d",&s[i]);
build(1,1,n);
for (int i=0;i<m;i++)
{
int k,a,b;
scanf("%d",&k);
if (k==1)
{
scanf("%d%d",&a,&b);
update(1,a,b);
}
else
{
LL res=-inf;
scanf("%d%d",&a,&b);
Tree tmp=query(1,a,b);
res=max(res,tmp.oo);
res=max(res,tmp.oe);
res=max(res,tmp.ee);
res=max(res,tmp.eo);
printf("%I64d\n",res);
}
}
}
}