【Wannafly挑戰賽10】D.小H的詢問(線段樹的區間合併)
阿新 • • 發佈:2019-01-25
記錄一個菜逼的成長。。
題目連結
來源:牛客網
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
小H給你一個數組{a},要求支援以下兩種操作:
0lr(1<=l<=r<=n) ,詢問區間[l,r]中權值和最大的有效子區間的權值和,一個子區間被認為是有效的當且僅當這個子區間中沒有兩個相鄰的偶數或者奇數。1xv(1<=x<=n,−109<=v<=109) ,將a[x]的值修改為v。
輸入描述:
第一行讀入兩個正整數n,m(1<=n,m<=10^5)
第二行讀入n個整數,第i個表示a[i](-10^9 <= a[i] <= 10^9)
接下來m行,每行三個數表示操作,描述見題目描述。
輸出描述:
輸出每個詢問的答案。
分析
算是經典的線段樹的區間合併。
可以說是模板題了吧。
先說結點的結構。
記錄區間的左右邊界的
記錄區間
記錄在區間
記錄區間
重點在如何合併。
現在有兩個區間
當
兩區間可以合併。
此時合併後的區間
這裡包含了兩層意思。
如果區間
如果區間
同理
反之兩區間不可以合併時
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define lson t<<1,l,mid
#define rson t<<1|1,mid+1,r
#define seglen(t) (node[t].r-node[t].l+1)
typedef long long LL;
typedef pair<LL,LL> PLL;
typedef pair<int,int> PII;
const LL INF = 0x3f3f3f3f;
const int maxn = 100000 + 10;
LL a[maxn];
struct Node{
int l,r;
LL sl,sr;
LL ans,sum;
Node(){l = r = 0;sum = -INF * maxn;}
Node operator + (const Node &ob)const {
Node ret ;
ret.l = l;ret.r = ob.r;
if((a[r]^a[ob.l])&1) {
ret.sum = sum + ob.sum;
ret.sl = max(sl,sum + ob.sl);
ret.sr = max(ob.sr,ob.sum + sr);
ret.ans = max(max(ans,ob.ans),sr + ob.sl);
}
else {
ret.sum = -INF * maxn;
ret.sl = sl;ret.sr = ob.sr;
ret.ans = max(ans,ob.ans);
}
return ret;
}
}node[maxn<<2];
void pushup(int t)
{
node[t] = node[t<<1] + node[t<<1|1];
}
void build(int t,int l,int r)
{
node[t].l = l;
node[t].r = r;
node[t].sum = -INF * maxn;
if (l == r) {
node[t].sl = node[t].sr = node[t].ans = node[t].sum = a[l];
return ;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(t);
}
void update(int t,int ind,LL v)
{
if(node[t].l == node[t].r) {
node[t].sl = node[t].sr = node[t].ans = node[t].sum = v;
return ;
}
int mid = (node[t].l + node[t].r) >> 1;
if(ind <= mid)update(t<<1,ind,v);
if(ind > mid)update(t<<1|1,ind,v);
pushup(t);
}
Node query(int t,int l,int r)
{
if(node[t].l >= l && r >= node[t].r) {
return node[t];
}
int mid = (node[t].l + node[t].r) >> 1;
if(l > mid)return query(t<<1|1,l,r);
if(r <= mid)return query(t<<1,l,r);
return query(t<<1,l,r) + query(t<<1|1,l,r);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)) {
for (int i = 1; i <= n; i++) scanf("%lld",a+i);
build(1,1,n);
while(m--) {
int ope,l,r;
scanf("%d%d%d",&ope,&l,&r);
if(ope) {
a[l] = r;
update(1,l,(LL)r);
}
else {
Node ret = query(1,l,r);
printf("%lld\n",ret.ans);
}
}
}
return 0;
}