T组数据
N个数字,M次操作
op=0:找出L-R区间内的最大‘值’
op=1:把a位置的数字换成b
对最大‘值’的定义:取区间内的最大子序列,需要保证子序列的下标为奇偶交替的
用线段树分别记录每个区间的
.........s1.......奇数位开始,奇数位结束
.........s2.......奇数位开始,偶数为结束
.........s3.......偶数位开始,偶数位结束
.........s4.......偶数位开始,奇数位结束
对每次询问分别处理4种情况的最大值即可
此题乍一看比较麻烦, 笔者刚开始想到dp,但没有思路,而此题又有很裸地线段树特点,于是用线段树做。此题与一般线段树不同的是,节点上记录的是几个值
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=100010;
const ll INF=-1e9;
int n,m;
ll t,a[N];
typedef struct
{
int left,right;
//.........s1.......奇数位开始,奇数位结束
//.........s2.......奇数位开始,偶数为结束
//.........s3.......偶数位开始,偶数位结束
//.........s4.......偶数位开始,奇数位结束
ll s1,s2,s3,s4;
}P;
P per[4*N];
typedef struct
{
ll s1,s2,s3,s4;
}data;
ll MAX(ll a,int b)
{
if(a>b)
return a;
return b;
}
ll MAX(ll a,ll b,ll c,ll d)
{
ll m1=max(a,b),m2=max(c,d);
return max(m1,m2);
}
void build(int id,ll left,ll right)
{
per[id].left=left;
per[id].right=right;
if(left==right)
{
if(left&1)
{
per[id].s1=a[left];
per[id].s2=INF;
per[id].s3=INF;
per[id].s4=INF;
}
else
{
per[id].s1=INF;
per[id].s2=INF;
per[id].s3=a[left];
per[id].s4=INF;
}
return;
}
else
{
int mid=(left+right)>>1,len1=id<<1,len2=id<<1|1;
build(len1,left,mid);
build(len2,mid+1,right);
ll as1,as2,as3,as4,bs1,bs2,bs3,bs4;
as1=per[len1].s1; as2=per[len1].s2;
as3=per[len1].s3; as4=per[len1].s4;
bs1=per[len2].s1; bs2=per[len2].s2;
bs3=per[len2].s3; bs4=per[len2].s4;
per[id].s1=MAX(as1,bs1,as1+bs4,as2+bs1);
per[id].s2=MAX(as2,bs2,as2+bs2,as1+bs3);
per[id].s3=MAX(as3,bs3,as3+bs2,as4+bs3);
per[id].s4=MAX(as4,bs4,as4+bs4,as3+bs1);
}
}
void update(int id,ll a,ll b)
{//cout<<"a= "<<a<<" b= "<<b<<endl;
if(per[id].left>a||per[id].right<a)
return;
if(per[id].left==per[id].right&&per[id].left==a)
{//cout<<"updata= "<<a<<" b= "<<b<<endl;
if(a&1)
per[id].s1=b;
else
per[id].s3=b;
}
else
{
ll mid=(per[id].left+per[id].right)>>1;
ll len1=id<<1,len2=len1+1;
if(mid<a)
update(len2,a,b);
else
if(mid>=a)
update(len1,a,b);
ll as1,as2,as3,as4,bs1,bs2,bs3,bs4;
as1=per[len1].s1; as2=per[len1].s2;
as3=per[len1].s3; as4=per[len1].s4;
bs1=per[len2].s1; bs2=per[len2].s2;
bs3=per[len2].s3; bs4=per[len2].s4;
per[id].s1=MAX(as1,bs1,as1+bs4,as2+bs1);
per[id].s2=MAX(as2,bs2,as2+bs2,as1+bs3);
per[id].s3=MAX(as3,bs3,as3+bs2,as4+bs3);
per[id].s4=MAX(as4,bs4,as4+bs4,as3+bs1);
}
}
data query(int id,ll l,ll r)
{
ll s;
if(per[id].left==l&&per[id].right==r)
{
data da;
da.s1=per[id].s1; da.s2=per[id].s2;
da.s3=per[id].s3; da.s4=per[id].s4;
return da;
}
if(per[id].left>r||per[id].right<l)
{
data da;
da.s1=INF; da.s2=INF;
da.s3=INF; da.s4=INF;
return da;
}
ll mid=(per[id].left+per[id].right)>>1;
ll len1=id<<1,len2=len1+1;
if(r<=mid)
return query(len1,l,r);
else
if(l>mid)
return query(len2,l,r);
else
{
data d1=query(len1,l,mid);
data d2=query(len2,mid+1,r);
data d3;
d3.s1=MAX(d1.s1,d2.s1,d1.s1+d2.s4,d1.s2+d2.s1);
d3.s2=MAX(d1.s2,d2.s2,d1.s1+d2.s3,d1.s2+d2.s2);
d3.s3=MAX(d1.s3,d2.s3,d1.s3+d2.s2,d1.s4+d2.s3);
d3.s4=MAX(d1.s4,d2.s4,d1.s3+d2.s1,d1.s4+d2.s4);
return d3;
}
}
int main()
{
int i,j;
ll l,r,k;
while(~scanf("%d",&t))
{
while(t--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
for(i=0;i<m;i++)
{
cin>>k>>l>>r;
if(k==0)
{
data da=query(1,l,r);
ll mmax=MAX(da.s1,da.s2,da.s3,da.s4);
cout<<mmax<<endl;
}
if(k==1)
{
update(1,l,r);
//for(i=1;i<=4*n;i++)
}
}
}
}
return 0;
}