线段树——vijos1083

https://vijos.org/p/1083
就是线段树啦,好像在洛谷也有怎么类似的一题;

struct tree{int l,r,x,y,v,sum;}T[1048576]

l,r就是区间啦,v表是这段区间的最优值;
sum是这一段的总和;
x是一定包括l点的最优值;
y是一定包括r点的最优值;
当然喽,因为一定要取公园所以可以负数;
更新

void up(int num){
    int x=num*2,y=x+1;
    T[num].v=max(T[x].v,T[y].v);
    T[num].v=max(T[num].v,T[x].y+T[y].x);
    T[num].sum=T[x].sum+T[y].sum;
    T[num].x=max(T[x].x,T[x].sum+T[y].x);
    T[num].y=max(T[y].y,T[y].sum+T[x].y);
}

不想讲什么了,反正是比较显然的啦,就是分类讨论;
然后我们查询答案,不是有一个区间l~r的;
这个区间会被线段树分成很多段;
那我们把这些段一个一个存下来从左到右合并成一个;
就好啦;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define Ll long long
using namespace std;
struct tree{int l,r,x,y,v,sum;}T[1048576],q[500000],temp;
int n,m,x,y,z,top;
void up(int num){
    int x=num*2,y=x+1;
    T[num].v=max(T[x].v,T[y].v);
    T[num].v=max(T[num].v,T[x].y+T[y].x);
    T[num].sum=T[x].sum+T[y].sum;
    T[num].x=max(T[x].x,T[x].sum+T[y].x);
    T[num].y=max(T[y].y,T[y].sum+T[x].y);
}
void maketree(int l,int r,int num){
    T[num].l=l; T[num].r=r;
    if(l==r){
        scanf("%d",&T[num].v);
        T[num].sum=T[num].x=T[num].y=T[num].v;
        return;
    }
    int mid=l+r>>1;
    maketree(l,mid  ,num*2  );
    maketree(mid+1,r,num*2+1);
    up(num);
}
void outit(int x,int y,int num){
    if(x<=T[num].l&&T[num].r<=y){
        q[++top]=T[num];
        return;
    }
    num=num+num;
    if(T[num  ].r>=x)outit(x,y,num  );
    if(T[num+1].l<=y)outit(x,y,num+1);
}
void init(int x,int v,int num){
    if(T[num].l==T[num].r){
        T[num].sum=T[num].x=T[num].y=T[num].v=v;
        return;
    }
    num=num*2;
    if(T[num  ].r>=x)init(x,v,num  );
    if(T[num+1].l<=x)init(x,v,num+1);
    up(num/2);
}
int main()
{
    scanf("%d%d",&n,&m);
    maketree(1,n,1);
    while(m--){
        scanf("%d%d%d",&z,&x,&y);
        if(z==1){
            if(x>y)swap(x,y);
            top=0;
            outit(x,y,1);
            for(int i=2;i<=top;i++){
                int x=i-1,y=i;
                temp.v=max(q[x].v,q[y].v);
                temp.v=max(temp.v,q[x].y+q[y].x);
                temp.sum=q[x].sum+q[y].sum;
                temp.x=max(q[x].x,q[x].sum+q[y].x);
                temp.y=max(q[y].y,q[y].sum+q[x].y);
                q[i]=temp;
            }
            printf("%d\n",q[top].v);
        }else init(x,y,1);
    }
}
posted @ 2017-04-29 11:02  largecube233  阅读(146)  评论(0编辑  收藏  举报