L - Traveling Merchant —— 线段树求区间内有方向的差值最大

This way

题意:

现在有一条线,所有位置都有一种商品,每个商品的价格为a[i],在周二到周四时,商品的价格增加pi,周五到周日每个商品的价格减少pi。现在一个商人在周一出发,从s到t。他只能买一次商品,卖一次商品,问你最大的理论是多少。

题解:

很容易发现,其实只有7种情况,也就是出发时间从1-7.然后就是查询区间中先买后卖的差值最大是多少。
我们只需要维护7个线段树。并且维护区间最大,最小,区间左到右的最大差值和右到左的最大差值即可。
左到右的差值最大为:

t[x][root].l_r=
max(t[x][root<<1|1].mx-t[x][root<<1].mi,
max(t[x][root<<1].l_r,t[x][root<<1|1].l_r));

也就是右儿子的最大值-左儿子的最小值,和两个儿子内部的答案取最大即可
在查询的时候,对于区间被分成两个的时候我们需要维护一下

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
#define ll long long
ll a[N],d[N],b[8][N];
struct node{
    ll mx,mi,l_r,r_l;
}t[8][N*4];
void push_up(int x,int root){
    t[x][root].mx=max(t[x][root<<1].mx,t[x][root<<1|1].mx);
    t[x][root].mi=min(t[x][root<<1].mi,t[x][root<<1|1].mi);

    t[x][root].l_r=max(t[x][root<<1|1].mx-t[x][root<<1].mi,max(t[x][root<<1].l_r,t[x][root<<1|1].l_r));
    t[x][root].r_l=max(t[x][root<<1].mx-t[x][root<<1|1].mi,max(t[x][root<<1].r_l,t[x][root<<1|1].r_l));
}
void build(int x,int l,int r,int root){
    if(l==r){
        t[x][root].mx=t[x][root].mi=b[x][l];
        return ;
    }
    int mid=l+r>>1;
    build(x,l,mid,root<<1);
    build(x,mid+1,r,root<<1|1);
    push_up(x,root);
}
void update(node& a,node b){
    a.l_r=max(a.l_r,max(b.l_r,b.mx-a.mi));
    a.r_l=max(a.r_l,max(b.r_l,a.mx-b.mi));
    a.mx=max(a.mx,b.mx);
    a.mi=min(a.mi,b.mi);
}
node query(int x,int l,int r,int root,int ql,int qr){
    if(l>=ql&&r<=qr)
        return t[x][root];
    int mid=l+r>>1;
    node ans;
    if(mid>=ql&&mid>=qr)
        ans=query(x,l,mid,root<<1,ql,qr);
    else if(mid<ql&&mid<qr)
        ans=query(x,mid+1,r,root<<1|1,ql,qr);
    else{
        ans=query(x,l,mid,root<<1,ql,qr);
        node ans1=query(x,mid+1,r,root<<1|1,ql,qr);
        update(ans,ans1);
    }
    return ans;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&a[i],&d[i]);
    for(int s=1;s<=7;s++){
        ll ad=0,f=1;
        for(int i=s;i<=n;i++){
            b[s][i]=a[i]+d[i]*ad;
            ad+=f;
            if(ad==3)f=-1;
            if(ad==0)f++;
        }
        ad=0,f=1;
        for(int i=s-1;i;i--){
            b[s][i]=a[i]+d[i]*ad;
            ad+=f;
            if(ad==3)f=-1;
            if(ad==0)f++;
        }
        build(s,1,n,1);
    }
    int q;
    scanf("%d",&q);
    while(q--){
        int l,r;
        scanf("%d%d",&l,&r);
        if(l<=r){
            int sta=l%7;
            if(sta==0)sta=7;
            printf("%lld\n",max(0ll,query(sta,1,n,1,l,r).l_r));
        }
        else{
            swap(l,r);
            int sta=r%7+1;
            printf("%lld\n",max(0ll,query(sta,1,n,1,l,r).r_l));
        }
    }
    return 0;
}

发布了530 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/104199865