codevs 3304フルーツ姉さんフルーツ街をぶらぶらI


-昨日の夜に私の線分の木のやり方を調整していないで、今日やっと来て、この問題の正解は線分の木かもしれないと感じて、前にDPという方法は少し引っ張って、しかし過ぎることができて、過ぎることができて良いQQQ*テーマのリンク:http://codevs.cn/problem/3304/ -最大値、最小値、答えの3つの値を同時に返すため、クエリ時に構造体型のAsk関数を定義することで、Ask_を単独で書く必要がなくなります.maxとAsk_min関数は、時間と労力を節約します.Ask関数を返すたびに、答えと右(左)区間の最大値を左(右)区間の最小値の値と比較することに注意してください.コード:
#include
#include
#include
#include
#include
using namespace std;

const int maxn=2e5+10,inf=1e8+10;
int n,m,Ans;
int a[maxn];
struct hh
{
    int l,r;
    int maxx,minn,ans1,ans2;
}tree[maxn<<2];
struct lxt
{
    int ma,mi,ans;
};

void build(int l,int r,int i)
{
    tree[i].l=l;
    tree[i].r=r;
    if(l==r) 
    {
        tree[i].minn=tree[i].maxx=a[l];
        tree[i].ans1=tree[i].ans2=0;
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    tree[i].minn=min(tree[i<<1].minn,tree[i<<1|1].minn);
    tree[i].maxx=max(tree[i<<1].maxx,tree[i<<1|1].maxx);
    tree[i].ans1=max(tree[i<<1|1].maxx-tree[i<<1].minn,max(tree[i<<1|1].ans1,tree[i<<1].ans1));
    tree[i].ans2=max(tree[i<<1].maxx-tree[i<<1|1].minn,max(tree[i<<1|1].ans2,tree[i<<1].ans2));
    if(tree[i].ans1<0) tree[i].ans1=0;
    if(tree[i].ans2<0) tree[i].ans2=0;
}
lxt ask_one(int l,int r,int i)
{
    lxt f;
    f.ans=0;
    f.mi=inf;
    f.ma=-inf;
    int lx=tree[i].l,rx=tree[i].r;
    if(lx>=l&&rx<=r)
    {
        f.ans=tree[i].ans1;
        f.ma=tree[i].maxx;
        f.mi=tree[i].minn;
        return f;
    }
    int mid=(lx+rx)>>1;
    lxt A,B;
    if(l<=mid) 
    {
        A=ask_one(l,r,i<<1); 
        f.ans=max(f.ans,A.ans);
        f.mi=min(f.mi,A.mi);
        f.ma=max(f.ma,A.ma);
    }
    if(r>mid) 
    {
        B=ask_one(l,r,i<<1|1);
        f.ans=max(f.ans,B.ans);
        f.mi=min(f.mi,B.mi);
        f.ma=max(f.ma,B.ma);
    }
    if(l<=mid&&r>mid) 
      f.ans=max(f.ans,B.ma-A.mi);
    return f;
}
lxt ask_two(int l,int r,int i)
{
    lxt f;
    f.ans=0;
    f.mi=inf;
    f.ma=-inf;
    int lx=tree[i].l,rx=tree[i].r;
    if(lx>=l&&rx<=r)
    {
        f.ans=tree[i].ans2;
        f.ma=tree[i].maxx;
        f.mi=tree[i].minn;
        return f;
    }

    int mid=(lx+rx)>>1;
    lxt A,B;
    if(l<=mid) 
    {
        A=ask_two(l,r,i<<1); 
        f.ans=max(f.ans,A.ans);
        f.mi=min(f.mi,A.mi);
        f.ma=max(f.ma,A.ma);
    }
    if(r>mid) 
    {
        B=ask_two(l,r,i<<1|1);
        f.ans=max(f.ans,B.ans);
        f.mi=min(f.mi,B.mi);
        f.ma=max(f.ma,B.ma);
    }
    if(l<=mid&&r>mid) 
      f.ans=max(f.ans,A.ma-B.mi);
    return f;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    build(1,n,1);
    scanf("%d",&m);
    for(int i=1;i<=m;++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        Ans=0;
        if(x<y) Ans=ask_one(x,y,1).ans;
        else if(x>y) Ans=ask_two(y,x,1).ans;
        printf("%d
"
,Ans); } return 0; }