题目描述:
小H给你一个数组{a},要求支持以下两种操作:
1. 0 l r(1<=l<=r<=n),询问区间[l,r]中权值和最大的有效子区间的权值和,一个子区间被认为是有效的当且仅当这个子区间中没有两个相邻的偶数或者奇数。
2. 1 x v(1<=x<=n,-109<=v<=109),将a[x]的值修改为v。
输入描述:
第一行读入两个正整数n,m(1<=n,m<=105)
第二行读入n个整数,第i个表示a[i](-109 <= a[i] <= 109)
接下来m行,每行三个数表示操作,描述见题目描述。
输出描述:
输出每个询问的答案。
输入:
10 10
-9 -8 -8 -8 2 -7 -5 2 2 3
0 3 5
0 4 4
0 2 4
1 6 6
1 1 6
1 5 9
0 1 2
1 5 -8
0 2 4
1 3 -2
输出:
2
-8
-8
6
-8
题解:又有更新又有查询,呢肯定是线段树了,因为每次查询的最大字段和必须要在合法区间,因此普通的区间查询肯定不行,我们考虑区间合并查询,对于当前小区间,无非就是左段合法区间的最大值或者右段合法区间的最大值,当两个区间合成一个大区间的话,答案无非有三种,假如合并出的中间出现新的合法区间,呢最大值在原有的基础上更新即可,定义4个变量即可。具体见代码。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100005
#define ll long long
int val[maxn],n,m;
struct node
{
int l,r;
ll lm,rm,mm,s;
}sum[maxn<<2];
node merge(node a,node b)
{
node c;
c.lm=a.lm;c.rm=b.rm;
c.mm=max(a.mm,b.mm);c.s=-1e18;
if((val[a.r]+val[b.l])%2)
{
c.mm=max(a.rm+b.lm,c.mm);
c.lm=max(a.lm,a.s+b.lm);
c.rm=max(b.rm,b.s+a.rm);
c.s=max((ll)-1e18,a.s+b.s);
}
c.l=a.l;c.r=b.r;
return c;
}
void build(int id,int l,int r)
{
if(l==r)
{
sum[id].l=sum[id].r=l;
sum[id].lm=sum[id].rm=sum[id].mm=sum[id].s=val[l];
return;
}
int mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
sum[id]=merge(sum[id*2],sum[id*2+1]);
}
void update(int id,int l,int r,int k,int v)
{
if(l==r)
{
sum[id].lm=sum[id].rm=sum[id].mm=sum[id].s=v;
return;
}
int mid=(l+r)/2;
if(k<=mid)
update(id*2,l,mid,k,v);
else
update(id*2+1,mid+1,r,k,v);
sum[id]=merge(sum[id*2],sum[id*2+1]);
}
node query(int id,int l,int r,int L,int R)
{
if(L<=l && R>=r)
return sum[id];
int mid=(l+r)/2;
if(R<=mid)
return query(id*2,l,mid,L,R);
if(L>mid)
return query(id*2+1,mid+1,r,L,R);
return merge(query(id*2,l,mid,L,R),query(id*2+1,mid+1,r,L,R));
}
int main(void)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
build(1,1,n);
while(m--)
{
int t,l,r;
scanf("%d%d%d",&t,&l,&r);
if(t==1)
{
val[l]=r;
update(1,1,n,l,r);
}
else
printf("%lld\n",query(1,1,n,l,r).mm);
}
return 0;
}
/*
10 10
-9 -8 -8 -8 2 -7 -5 2 2 3
0 3 5
0 4 4
0 2 4
1 6 6
1 1 6
1 5 9
0 1 2
1 5 -8
0 2 4
1 3 -2
*/