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;
}

 

posted @ 2019-05-02 21:00  冥想选手  阅读(139)  评论(0编辑  收藏  举报