luogu P4513 小白逛公园 (区间合并)
链接:https://www.luogu.org/problemnew/show/P4513
思路: 很基础的区间合并,开四个数组:
num: 区间数字的和
lsum:从左端点起最大连续字段和
rsum:从右端点起最大连续字段和
sum:区间最大连续字段和
然后按照以前合并的思路合并下就完事了。
好久没写区间合并的题。。还被卡了一阵子,属实弟弟
实现代码;
#include<bits/stdc++.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define ls rt<<1 #define rs rt<<1|1 const int M = 1e6+10; struct node{ int sum,lsum,num,rsum; }t[M<<2]; void pushup(int rt){ t[rt].num = t[ls].num + t[rs].num; t[rt].sum = max(t[ls].sum,t[rs].sum); t[rt].lsum = max(t[ls].lsum,t[rs].lsum+t[ls].num); t[rt].rsum = max(t[rs].rsum,t[ls].rsum+t[rs].num); t[rt].sum = max(t[rt].sum,t[ls].rsum+t[rs].lsum); } void update(int p,int c,int l,int r,int rt){ if(l == r){ t[rt].sum = t[rt].lsum = t[rt].rsum = t[rt].num = c; return ; } int mid = (l + r) >> 1; if(p <= mid) update(p,c,lson); else update(p,c,rson); pushup(rt); } node query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r){ return t[rt]; } int mid = (l + r) >> 1; if(R <= mid) return query(L,R,lson); else if(L > mid) return query(L,R,rson); else{ node t1 = query(L,R,lson),t2 = query(L,R,rson),ret; ret.lsum = max(t1.lsum,t2.lsum+t1.num); ret.rsum = max(t2.rsum,t1.rsum+t2.num); ret.sum = max(max(t1.sum,t2.sum),t1.rsum+t2.lsum); return ret; } } int main() { int n,q,x,y,op; scanf("%d%d",&n,&q); for(int i = 1;i <= n;i ++) scanf("%d",&x),update(i,x,1,n,1); while(q--){ scanf("%d%d%d",&op,&x,&y); if(op == 1){ if(y < x) swap(x,y); printf("%d\n",query(x,y,1,n,1).sum); } else{ update(x,y,1,n,1); } } return 0; }