zoukankan      html  css  js  c++  java
  • codevs3304水果姐逛街(线段数)

    3304 水果姐逛水果街Ⅰ

     

     时间限制: 2 s
     空间限制: 256000 KB
     题目等级 : 钻石 Diamond
     
    题目描述 Description

    水果姐今天心情不错,来到了水果街。

    水果街有n家水果店,呈直线结构,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样。

    学过oi的水果姐迅速发现了一个赚钱的方法:在某家水果店买一个水果,再到另外一家店卖出去,赚差价。

    就在水果姐窃喜的时候,cgh突然出现,他为了为难水果姐,给出m个问题,每个问题要求水果姐从第x家店出发到第y家店,途中只能选一家店买一个水果,然后选一家店(可以是同一家店,但不能往回走)卖出去,求每个问题中最多可以赚多少钱。

    输入描述 Input Description

    第一行n,表示有n家店

    下来n个正整数,表示每家店一个苹果的价格。

    下来一个整数m,表示下来有m个询问。

    下来有m行,每行两个整数x和y,表示从第x家店出发到第y家店。

    输出描述 Output Description

    有m行。

    每行对应一个询问,一个整数,表示面对cgh的每次询问,水果姐最多可以赚到多少钱。

    样例输入 Sample Input

    10
    2 8 15 1 10 5 19 19 3 5 
    4
    6 6
    2 8
    2 2
    6 3

    样例输出 Sample Output

    0
    18
    0
    14

    数据范围及提示 Data Size & Hint

    0<=苹果的价格<=10^8

    0<n,m<=200000

    /*
    这一道题是有一排商店,可以买水果也可以卖水果,买水果和卖水果的价钱一样。 
    问你从商店x走到商店y,买卖所得最大收益是多少。 
    我们可以发现朴素的办法是一路扫过去,记录当前最小值,然后更新收益。 
    这样应该会T(我没试过) 这样丢失了很多信息。 
    我们考虑一下能不能存起来。 发现解满足区间加法。 
    即【L,R】中最大的收益要么是【L,K】中的收益,要么是【K,R】中的收益(端点重合不影响),要么是【K,R】中的最大值减去【L,K】中的最小值。
    这是针对从左往右走的。 
    于是乎我们可以用线段树来维护这些信息。 
    因为我们有可能从左往右走,也可能从右往左走,所以记个f数组,f[0]表示从线段树中下标小的向下标大的走所得的最大收益。 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 200010
    #define inf 0x7fffffff
    
    using namespace std;
    int n,m,num,a[maxn];
    struct node
    {
        int lc,rc;
        int l,r;
        int smin,smax;
        int ansl,ansr;
    }t[maxn*4];
    
    int init()
    {
        int x=0;char s;bool f=0;s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9')
          {
              x=x*10+s-'0';
              s=getchar();
          }
        return x;
    }
    
    void update(int k)
    {
        t[k].smin=min(t[t[k].lc].smin,t[t[k].rc].smin);
        t[k].smax=max(t[t[k].lc].smax,t[t[k].rc].smax);
        t[k].ansl=max(t[t[k].lc].ansl,t[t[k].rc].ansl);
        t[k].ansl=max(t[k].ansl,t[t[k].rc].smax-t[t[k].lc].smin);
        t[k].ansr=max(t[t[k].lc].ansr,t[t[k].rc].ansr);
        t[k].ansr=max(t[k].ansr,t[t[k].lc].smax-t[t[k].rc].smin);
    }
    
    void Build(int ll,int rr)
    {
        int k=++num;
        t[k].l=ll;t[k].r=rr;
        if(ll==rr)
          {
            t[k].smin=t[k].smax=a[ll];
            return;
          }
        t[k].lc=num+1;
        Build(ll,(ll+rr)/2);
        t[k].rc=num+1;
        Build((ll+rr)/2+1,rr);
        update(k);
    }
    
    int findmin(int k,int ll,int rr)
    {
        if(ll==t[k].l&&rr==t[k].r)return t[k].smin;
        int mid=(t[k].l+t[k].r)/2;
        if(rr<=mid)return findmin(t[k].lc,ll,rr);
        else if(ll>mid)return findmin(t[k].rc,ll,rr);
        else return min(findmin(t[k].lc,ll,mid),findmin(t[k].rc,mid+1,rr));
    }
    
    int findmax(int k,int ll,int rr)
    {
        if(ll==t[k].l&&rr==t[k].r)return t[k].smax;
        int mid=(t[k].l+t[k].r)/2;
        if(rr<=mid)return findmax(t[k].lc,ll,rr);
        else if(ll>mid)return findmax(t[k].rc,ll,rr);
        else return max(findmax(t[k].lc,ll,mid),findmax(t[k].rc,mid+1,rr));
    }
    
    int findl(int k,int ll,int rr)
    {
        if(ll==t[k].l&&rr==t[k].r)return t[k].ansl;
        int mid=(t[k].l+t[k].r)/2;
        if(rr<=mid)return findl(t[k].lc,ll,rr);
        else if(ll>mid)return findl(t[k].rc,ll,rr);
        else
          {
              int maxx=0;
              maxx=max(findl(t[k].lc,ll,mid),findl(t[k].rc,mid+1,rr));
              maxx=max(maxx,findmax(t[k].rc,mid+1,rr)-findmin(t[k].lc,ll,mid));
              return maxx;
          }
    }
    
    int findr(int k,int ll,int rr)
    {
        if(ll==t[k].l&&rr==t[k].r)return t[k].ansr;
        int mid=(t[k].l+t[k].r)/2;
        if(rr<=mid)return findr(t[k].lc,ll,rr);
        else if(ll>mid)return findr(t[k].rc,ll,rr);
        else
          {
              int maxx=0;
              maxx=max(findr(t[k].lc,ll,mid),findr(t[k].rc,mid+1,rr));
              maxx=max(maxx,findmax(t[k].lc,ll,mid)-findmin(t[k].rc,mid+1,rr));
              return maxx;
          }
    }
    
    int main()
    {
        n=init();
        for(int i=1;i<=n;i++)
          a[i]=init();
        for(int i=1;i<=maxn*2;i++)
          t[i].smin=inf;
        Build(1,n);
        int x,y;
        m=init();
        for(int i=1;i<=m;i++)
          {
              x=init();y=init();
              if(x==y)
                {
                    printf("0
    ");
                    continue;
              }
            if(x<y)printf("%d
    ",findl(1,x,y));
            else printf("%d
    ",findr(1,y,x));
          }
        return 0;
    }
    心若向阳,无言悲伤
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    向SDE加入图形的时候出现Update fail,5019
    在两台机器上安装分别安装oracle和arcsde
    Maxthon与IE的Cookie冲突
    数据迁移如何不需要中止业务
    ArcSde注册版本后的表
    小心注释掉的js代码也会引起错误
    vb.net对循环内的变量分配和初始化的处理
    一个webservice的初级例子
    事务处理
    ado.net 相对于ado主要有哪些改进
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6353649.html
Copyright © 2011-2022 走看看