• SPOJ 1557(线段树)


    题意大概是说给定一个区间,求最大连续和

    完全不会,学习了半天

    大概可以理解为一个线段树点更新,区间询问的题目,但是构造和理解起来相对难许多。

    这里相同数的处理还是蛮有意思。用pre[i]记录i上一次出现的位置。所以update的时候跳过这个位置就好

    用离线算法,将询问区间按r排序后,从第一个至最后一个数依次加入线段树,同时维护四个值:

    1.sum 目前区间和

    2.maxo 最大区间和

    3.lazy 待下传的和

    4.lazyo 待下传的最大可更新值

    最关键的是pushdown函数

    sum、lazy和普通的更新没什么区别,重点在于maxo和lazyo

    可以注意到,当lazy<=0时,lazyo是一直为0的。因为如果加入的连续和<=0,maxo不可能被更新

    lazy和lazyo不可分别写一个if,因为lazy将更新sum,而sum的更新可能会改变maxo

    具体看代码

    #include"cstdio"
    #include"queue"
    #include"cmath"
    #include"stack"
    #include"iostream"
    #include"algorithm"
    #include"cstring"
    #include"queue"
    #include"map"
    #include"vector"
    #define ll long long
    #define mems(a,b) memset(a,b,sizeof(a))
    #define ls pos<<1
    #define rs pos<<1|1
    
    using namespace std;
    const int MAXN = 100500;
    const int MAXE = 200500;
    const int INF = 0x3f3f3f;
    
    struct node{
        int l,r;
        ll sum,maxo,lazyo,lazy;
    }node[MAXN<<2];
    
    struct nod{
        int a,b,id;
    }que[MAXN];
    
    int pre[MAXN*2+10];
    ll ans[MAXN],x[MAXN];
    
    bool cmp(nod x,nod y){
        return x.b<y.b;
    }
    
    void build(int l,int r,int pos){
        node[pos].l=l;
        node[pos].r=r;
        node[pos].lazy=node[pos].lazyo=0;
        node[pos].sum=node[pos].maxo=0;
        if(l==r) return;
        int mid=(l+r)>>1;;
        build(l,mid,pos<<1);
        build(mid+1,r,pos<<1|1);
    }
    
    void pushup(int pos){
        node[pos].sum=max(node[ls].sum,node[rs].sum);
        node[pos].maxo=max(node[ls].maxo,node[rs].maxo);
    }
    
    void pushdown(int pos){
        if(node[pos].lazy||node[pos].lazyo){
            node[ls].lazyo=max(node[ls].lazyo,node[ls].lazy+node[pos].lazyo);
            node[ls].maxo=max(node[ls].maxo,node[ls].sum+node[pos].lazyo);
            node[ls].lazy+=node[pos].lazy;
            node[ls].sum+=node[pos].lazy;
    
            node[rs].lazyo=max(node[rs].lazyo,node[rs].lazy+node[pos].lazyo);
            node[rs].maxo=max(node[rs].maxo,node[rs].sum+node[pos].lazyo);
            node[rs].lazy+=node[pos].lazy;
            node[rs].sum+=node[pos].lazy;
    
            node[pos].lazy=node[pos].lazyo=0;
        }
    }
    
    void update(int l,int r,int pos,int add){
        if(l<=node[pos].l&&node[pos].r<=r){
            node[pos].sum+=add;
            node[pos].lazy+=add;
            node[pos].lazyo=max(node[pos].lazyo,node[pos].lazy);
            node[pos].maxo=max(node[pos].sum,node[pos].maxo);
            return;
        }
        pushdown(pos);
        int mid=(node[pos].l+node[pos].r)>>1;
        if(l<=mid) update(l,r,ls,add);
        if(r>mid) update(l,r,rs,add);
        pushup(pos);
    }
    
    ll query(int l,int r,int pos){
        if(l<=node[pos].l&&node[pos].r<=r){
            return node[pos].maxo;
        }
        ll t=0;
        pushdown(pos);
        int mid=(node[pos].l+node[pos].r)>>1;
        if(l<=mid) t=max(t,query(l,r,ls));
        if(r>mid) t=max(t,query(l,r,rs));
        return t;
    }
    
    int main(){
        int n,q;
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n)){
            for(int i=1;i<=n;i++) scanf("%lld",&x[i]);
            build(1,n,1);
            scanf("%d",&q);
            for(int i=0;i<q;i++){
                scanf("%d%d",&que[i].a,&que[i].b);
                que[i].id=i;
            }
            sort(que,que+q,cmp);
            mems(pre,0);
            int j=0;
            for(int i=1;i<=n;i++){
                update(pre[MAXN+x[i]]+1,i,1,x[i]);
                pre[MAXN+x[i]]=i;
                while(j<q&&que[j].b==i){
                    ans[que[j].id]=query(que[j].a,que[j].b,1);
                    j++;
                }
            }
            for(int i=0;i<q;i++) printf("%lld
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    dsadsad
    线程池,封装使用,实现控制子线程
    如何能很好地安排好自己的时间?
    中文验证码
    海量数据处理专题(七)——数据库索引及优化
    java tree jtree的使用
    基于Cookie的单点登录(SSO)系统介绍
    急求VS2010的Cookie解决方法
    微软企业库5.0 学习之路系列文章索引
    Net 4.0 Parallel编程(八)Task中的数据共享(中)
  • 原文地址:https://www.cnblogs.com/luxiaoming/p/5122303.html
Copyright © 2020-2023  润新知