Traveling Merchant (2019 ICPC North American Qualifier Contest L)

题意:

给出一个序列,每个点都有货物其价格是周期变化的,只能从起点走向终点,每走一个点经过一天,不能再点上停留,给出起点终点问可获得的最大价值。

思路:

: 线段树维护 Max , Min 和 右子树的Max-左子树Min 的最大值(st) 但这样记录答案只是每个子树上的的答案,所以在查询时,还需要维护一下左右子树之间的答案
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define ls (now<<1)
#define rs (now<<1|1)
#define lson l,mid,ls
#define rson mid+1,r,rs

#define int long long

#define Bug cout<<"here\n";
const int maxn=2e5+10;

struct node{
    int Max,Min,l,r;
}e[20][maxn*4];

int b[10][maxn];

void up(node t[],int now){

    t[now].l=t[rs].Max-t[ls].Min;
    t[now].l=max(t[now].l,max(t[ls].l,t[rs].l));

    t[now].r=t[ls].Max-t[rs].Min;
    t[now].r=max(t[now].r,max(t[ls].r,t[rs].r));

    t[now].Max=max(t[ls].Max,t[rs].Max);
    t[now].Min=min(t[ls].Min,t[rs].Min);
}

void n_up(node &x,node a,node b)
{
    x.l=b.Max-a.Min;
    x.l=max(x.l,max(b.l,a.l));


    x.r=a.Max-b.Min;
    x.r=max(x.r,max(b.r,a.r));

    x.Max=max(a.Max,b.Max);
    x.Min=min(a.Min,b.Min);
}

void built(node t[], int st,int l,int r,int now)
{
    int mid=(l+r)>>1;
    if(l>r) return ;
    t[now].l=t[now].r=0;
    t[now].Max=t[now].Min=0;
    while(l==r)
    {
        int k=(l+st)%7;
        if(k==0) k=7;
        if(st>=7)
        {
            k=8-k;
        }
        t[now].Max=t[now].Min=b[k][l];return ;
    }
    built(t,st,lson);
    built(t,st,rson);
    up(t,now);

}

node query(node t[],int l,int r,int L,int R,int now)
{
    int mid=(l+r)>>1;
    if(L<=l&&r<=R)
        return t[now];
    node ans,ans3=(node){0,0,0,0};
    if(L<=mid) ans=query(t,l,mid,L,R,now<<1);
    if(R>mid){
        node ans2=query(t,mid+1,r,L,R,now<<1|1);
        if(L<=mid) n_up(ans3,ans,ans2);
        else ans3=ans2;
    }
    else ans3=ans;
    return ans3;
}

#undef int
int main()
{
#define int long long
    int n;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        int v,d;
        scanf("%lld%lld",&v,&d);
        for(int j=1;j<=4;j++)
            b[j][i]=b[7-j+1][i]=v+(j-1)*d;
    }
    for(int i=1;i<=14;i++)
        built(e[i],i-1,1,n,1);
    int t;
    scanf("%lld",&t);
    while(t--)
    {
        int l,r;
        scanf("%lld%lld",&l,&r);
        if(l<r)
        {
            int k=(9-l%7)%7;
            if(k==0) k=7;
            int ans=query(e[k],1,n,l,r,1).l;
            printf("%lld\n",max(ans,1ll*0));
        }
        else
        {
            int k=(l%7);
            if(k==0)k=7;
            k=15-k;
            int ans=query(e[k],1,n,r,l,1).r;
            printf("%lld\n",max(ans,1ll*0));
        }
    }
    return 0;
}
posted @ 2019-10-30 17:01  Minun  阅读(403)  评论(0编辑  收藏  举报