zoukankan      html  css  js  c++  java
  • poj 2750 Potted Flower 夜

    http://poj.org/problem?id=2750

    最近在poj上做的线段树题 c++提交要比g++提交快很多,

    我知道c++要快一些,不过快的有点离谱了吧,都左右是否超时了

    题目大意:

    n盆花围成圈 每盆花都有它的value

    要做一个弧形长椅 不能是一个圆,因为必须有缺口,使得长椅附近花的value值和最大

    m次替换 每替换一次问替换后的最佳答案

    本题的难点在于环,因为线段树的建立是线状的

    所以在求最终答案是要注意

    线段树要保存本段从左起最大值,最小值,从右起最大值,最小值,和总体最大值,最小值,总和

    最大值和最小值都必须至少包含一盆花

    这都是为求最后答案做准备。

    最后答案基本分两种

    1.最小值为正,此时用最大减最小就可以了(因为必须有缺口)

    2.最小值为负,有可能是根的最大值,但也要考虑它是环的特性(判定缺口的位置),具体见代码注释。

    代码及其注释:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const int N=100005;
    struct node
    {
        int l,r;
        int highest,lhighest,rhighest;
        int lowest ,llowest, rlowest;
        int sum;
    }mem[N*3];
    int value[N];
    int MAX(int a,int b,int c)
    {
        if(b>a)a=b;
        if(c>a)a=c;
        return a;
    }
    int MIN(int a,int b,int c)
    {
        if(b<a)a=b;
        if(c<a)a=c;
        return a;
    }
    int MAX(int a,int b,int c,int d)
    {
        if(b>a)a=b;
        if(c>a)a=c;
        if(d>a)a=d;
        return a;
    }
    void build(int x,int l,int r)
    {
        mem[x].l=l;
        mem[x].r=r;
        if(l==r)//叶子结点 值的确定
        {
            mem[x].highest=value[l];
            mem[x].lhighest=value[l];
            mem[x].rhighest=value[l];
            mem[x].lowest=value[l];
            mem[x].llowest=value[l];
            mem[x].rlowest=value[l];
            mem[x].sum=value[l];
        }
        else
        {
            int mid=(l+r)>>1;
            build(x*2,l,mid);
            build(x*2+1,mid+1,r);
            mem[x].sum=mem[x*2].sum+mem[x*2+1].sum;//各种合并,要注意的是不能产生不连接状况
            mem[x].lhighest=max(mem[x*2].lhighest,mem[x*2].sum+mem[x*2+1].lhighest);
            mem[x].rhighest=max(mem[x*2+1].rhighest,mem[x*2+1].sum+mem[x*2].rhighest);
            mem[x].highest=MAX(mem[x].lhighest,mem[x].rhighest,mem[x*2].rhighest+mem[x*2+1].lhighest);
            mem[x].llowest=min(mem[x*2].llowest,mem[x*2].sum+mem[x*2+1].llowest);
            mem[x].rlowest=min(mem[x*2+1].rlowest,mem[x*2+1].sum+mem[x*2].rlowest);
            mem[x].lowest=MIN(mem[x*2].lowest,mem[x*2+1].lowest,mem[x*2].rlowest+mem[x*2+1].llowest);
        }
    
    }
    void findmin(int x,int i,int b)
    {
        if(mem[x].l==mem[x].r)//修改叶子结点值
        {
            mem[x].lowest=b;
            mem[x].llowest=b;
            mem[x].rlowest=b;
            mem[x].highest=b;
            mem[x].lhighest=b;
            mem[x].rhighest=b;
            mem[x].sum=b;
        }
        else
        {
            int mid=(mem[x].l+mem[x].r)>>1;
            if(i<=mid)//判定往哪搜
            findmin(x*2,i,b);
            else
            findmin(x*2+1,i,b);
            mem[x].sum=mem[x*2].sum+mem[x*2+1].sum;//各种合并,要注意的是不能产生不连接状况
            mem[x].lhighest=max(mem[x*2].lhighest,mem[x*2].sum+mem[x*2+1].lhighest);
            mem[x].rhighest=max(mem[x*2+1].rhighest,mem[x*2+1].sum+mem[x*2].rhighest);
            mem[x].highest=MAX(mem[x].lhighest,mem[x].rhighest,mem[x*2].rhighest+mem[x*2+1].lhighest);
            mem[x].llowest=min(mem[x*2].llowest,mem[x*2].sum+mem[x*2+1].llowest);
            mem[x].rlowest=min(mem[x*2+1].rlowest,mem[x*2+1].sum+mem[x*2].rlowest);
            mem[x].lowest=MIN(mem[x*2].lowest,mem[x*2+1].lowest,mem[x*2].rlowest+mem[x*2+1].llowest);
        }
    }
    int main()
    {
        //freopen("data.txt","r",stdin);
        int n;
        scanf("%d",&n);
        int M=0;
            for(int i=1;i<=n;++i)
            {
                scanf("%d",&value[i]);
                M=value[i];
            }
            build(1,1,n);
            int m;
            scanf("%d",&m);
            while(m--)
            {
                int i,b;
                scanf("%d %d",&i,&b);
                findmin(1,i,b);
                int ans;
                if(mem[1].lowest>0)
                {
                    ans=mem[1].highest-mem[1].lowest;
                }
                else
                {//考虑到他是环的状况所以 这里要仔细呀 可能是根结点最大,对于环
                    //1.缺口是线段了两头。2.缺口在左半。3.缺口在右半
                    ans=MAX(mem[1].highest,mem[2].lhighest+mem[3].rhighest,mem[2].sum-mem[2].lowest+mem[3].sum,
                            mem[3].sum-mem[3].lowest+mem[2].sum);
                }
                printf("%d\n",ans);
    
            }
        return 0;
    }
    

      

  • 相关阅读:
    ORM是什么?
    mysql 杂谈
    IO model之IO多路复用的触发方式
    IO model之select poll epoll IO多路复用介绍
    IO model
    事件驱动模型介绍
    函数
    商品程序
    随机生成密码
    import radom 和import string
  • 原文地址:https://www.cnblogs.com/liulangye/p/2548311.html
Copyright © 2011-2022 走看看