小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行,每行三个数表示操作,描述见题目描述。
输出描述:
输出每个询问的答案。
思路:维护区间的信息:端点奇偶性,靠左和靠右和靠中间的最大值,其中靠中间包含靠左和靠右,合并一下就好了。
# include <bits/stdc++.h>
# define lson l,mid,id<<1
# define rson mid+1,r,id<<1|1
using namespace std;
typedef long long LL;
const int maxn = 1e5+30;
struct node
{
LL sum, lm, rm, mm;
int lf, rf, ok;
}nod[maxn*4];
node merge(node l, node r)
{
node tmp;
tmp.ok = 0;
tmp.mm = max(l.mm, r.mm);
tmp.lf = l.lf; tmp.rf = r.rf;
tmp.rm = r.rm; tmp.lm = l.lm;
if(l.rf^r.lf)
{
tmp.mm = max(tmp.mm, l.rm+r.lm);
if(r.ok) tmp.rm = max(tmp.rm, l.rm+r.sum);
if(l.ok) tmp.lm = max(tmp.lm, r.lm+l.sum);
if(l.ok && r.ok)
{
tmp.ok = 1;
tmp.sum = l.sum + r.sum;
}
}
return tmp;
}
void build(int l, int r, int id)
{
if(l==r)
{
scanf("%lld",&nod[id].sum);
nod[id].lm = nod[id].rm = nod[id].mm = nod[id].sum;
nod[id].lf = nod[id].rf = nod[id].sum&1;
nod[id].ok = 1;
return;
}
int mid = l+r>>1;
build(l, mid, id<<1);
build(mid+1, r, id<<1|1);
nod[id] = merge(nod[id<<1], nod[id<<1|1]);
}
node query(int L, int R, int l, int r, int id)
{
if(L<=l && R>=r) return nod[id];
int mid = l+r>>1;
if(R <= mid) return query(L, R, lson);
else if(L > mid) return query(L, R, rson);
else return merge(query(L, R, lson),query(L, R, rson));
}
void update(int pos, int num, int l, int r, int id)
{
if(l==r)
{
nod[id].sum = nod[id].lm = nod[id].rm = nod[id].mm = num;
nod[id].lf = nod[id].rf = num&1;
nod[id].ok = 1;
return;
}
int mid = l+r>>1;
if(pos <= mid) update(pos, num, lson);
else update(pos, num, rson);
nod[id] = merge(nod[id<<1], nod[id<<1|1]);
}
int main()
{
int n, m;
scanf("%d%d",&n,&m);
build(1, n, 1);
while(m--)
{
int op, l, r;
scanf("%d%d%d",&op,&l,&r);
if(op == 0)
printf("%lld\n",query(l,r,1,n,1).mm);
else
update(l, r, 1, n, 1);
}
return 0;
}