CDOJ1598-線段樹合併(2017 UESTC Training for Data Structures G)

傳送門:CDOJ1598



題目大意:


給你n個數m次操作,有兩種操作

1,詢問區間[a,b]的 最大連續子區間

2,將第pos個數變爲X


題目思路:


線段樹區間和並,對於這題我們需維護個區間和和區間最大連續和向左向右最大連續和

對於向上更新時,父區間向左向右連續和爲爲子區間向左向右連續和和向左向右和加上

相反區間向左向右連續和,這個就和求最大字段和一樣,最大連續和左右子區間最大連續和

和中間連續和的最大值,查詢這裏我們用普通的方法是不行的,因爲我們這裏不好維左右連續

和的長度,所以查詢時可能會越界,所以我們要在要查的區間裏不斷向右合併更新,最後就是這個

詢問區間的最值,我們這裏可以用個全局變量來更新查詢




AC代碼:


#include<bits/stdc++.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn = 1e6;
struct st
{
    int sum,summax,lsum,rsum;
}Tree[maxn<<1];
void pushup(int rt)
{
    Tree[rt].lsum = max(Tree[rt<<1].lsum,Tree[rt<<1].sum+Tree[rt<<1|1].lsum);
    Tree[rt].rsum = max(Tree[rt<<1|1].rsum,Tree[rt<<1|1].sum+Tree[rt<<1].rsum);
    Tree[rt].sum = Tree[rt<<1].sum+Tree[rt<<1|1].sum;
    Tree[rt].summax = max(max(Tree[rt<<1].summax,Tree[rt<<1|1].summax),Tree[rt<<1].rsum+Tree[rt<<1|1].lsum);
}

void build(int l,int r,int rt)
{

    if(l==r)
    {
        int x;scanf("%d",&x);
        Tree[rt].lsum=Tree[rt].rsum= Tree[rt].sum = Tree[rt].summax = x;
        return ;
    }
    int mid = (l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}

int lsum,rsum,sum,summax;

void quary(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        //在查找區間內不斷更新,從左到右(性質)
        
        if(summax == 1e9)
        {
            summax = Tree[rt].summax;
            lsum = Tree[rt].lsum;
            rsum = Tree[rt].rsum;
            sum = Tree[rt].sum;
            return ;
        }

        summax = max(max(summax,Tree[rt].summax),rsum+Tree[rt].lsum);
        lsum = max(lsum,sum+Tree[rt].lsum);
        rsum = max(Tree[rt].rsum,Tree[rt].sum+rsum);
        sum = sum+Tree[rt].sum;

        return ;
    }
    int mid = (l+r)>>1;
    if(L<=mid)quary(L,R,lson);
    if(R>mid)quary(L,R,rson);
}

void updata(int l,int r,int rt,int pos,int v)
{
    if(l==r)
    {
        Tree[rt].lsum =v;
        Tree[rt].rsum=v;
        Tree[rt].sum=v;
        Tree[rt].summax=v;
        return ;
    }
    int mid = (l+r)>>1;
    if(pos<=mid)
    {
        updata(lson,pos,v);
    }
    else updata(rson,pos,v);
    pushup(rt);
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,n,1);
    while(m--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(a==1)
        {
            lsum = rsum = sum = summax = 1e9;
            quary(b,c,1,n,1);
            printf("%d\n",summax);
        }
        else
        {
            updata(1,n,1,b,c);
        }
    }
    return 0;
}




max{Ap+Ap+1++Aq

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章