2019 ICPC North America Qualifier Contest L题 Traveling Merchant(线段树)

我们观察到只有查询操作。

这个查询可以通过线段树来实现,因为可以通过维护最大最小值来维护差值最大值,因为是一个星期,所以容易相当答案是关于周期循环的,因此建立七棵线段树。

恶心的是有两个方向,因此我们要建十四棵线段树维护

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
const int inf=1e9;
const int mod=1e9+7;
struct node{
    int l,r;
    int lans,rans,mx,mi;
}tr[15][N<<2];
struct seg{
    int lans,rans,mx,mi;
};
int a[15][N];
int n;
void pushup(node t[],int u){
    t[u].lans=max(t[u<<1].lans,t[u<<1|1].lans);
    t[u].lans=max(t[u].lans,t[u<<1|1].mx-t[u<<1].mi);
    t[u].rans=max(t[u<<1].rans,t[u<<1|1].rans);
    t[u].rans=max(t[u].rans,t[u<<1].mx-t[u<<1|1].mi);
    t[u].mx=max(t[u<<1].mx,t[u<<1|1].mx);
    t[u].mi=min(t[u<<1].mi,t[u<<1|1].mi);
}
void build(node t[],int st,int u,int l,int r){
    if(l==r){
        int k=(l+st)%7;
        if(k==0) k=7;
        if(st>=7){
            k=8-k;
        }
        t[u]={l,r,0,0,a[k][l],a[k][l]};
    }
    else{
        t[u]={l,r};
        int mid=l+r>>1;
        build(t,st,u<<1,l,mid);
        build(t,st,u<<1|1,mid+1,r);
        pushup(t,u);
    }
}
seg query(node t[],int u,int l,int r){
    if(t[u].l>=l&&t[u].r<=r){
        return seg{t[u].lans,t[u].rans,t[u].mx,t[u].mi};
    }
    int mid=t[u].l+t[u].r>>1;
    seg ans={0,0,0,inf};
    seg tmp,tmp1;
    if(l<=mid){
        tmp=query(t,u<<1,l,r);
        ans.lans=max(ans.lans,tmp.lans);
        ans.rans=max(ans.rans,tmp.rans);
        ans.mx=max(ans.mx,tmp.mx);
        ans.mi=min(ans.mi,tmp.mi);
    }
    if(r>mid){
        tmp1=query(t,u<<1|1,l,r);
        ans.lans=max(ans.lans,tmp1.lans);
        ans.rans=max(ans.rans,tmp1.rans);
        ans.mx=max(ans.mx,tmp1.mx);
        ans.mi=min(ans.mi,tmp1.mi);
        if(l<=mid){
            ans.lans=max(ans.lans,tmp1.mx-tmp.mi);
            ans.rans=max(ans.rans,tmp.mx-tmp1.mi);
        }
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    int i,j;
    for(i=1;i<=n;i++){
        int x,d;
        cin>>x>>d;
        for(j=1;j<=4;j++){
            a[j][i]=a[7-j+1][i]=x+d*(j-1);
        }
    }
    for(i=1;i<=14;i++){
        build(tr[i],i-1,1,1,n);
    }
    int m;
    cin>>m;
    while(m--){
        int l,r;
        cin>>l>>r;
        if(l<r){
            int k=(9-l%7)%7;
            if(k==0) k=7;
            int ans=query(tr[k],1,l,r).lans;
            ans=max(ans,0);
            cout<<ans<<endl;
        }
        else{
            int k=(l%7);
            if(k==0)k=7;
            k=15-k;
            swap(l,r);
            int ans=query(tr[k],1,l,r).rans;
            ans=max(ans,0);
            cout<<ans<<endl;
        }
    }
    return 0;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/14394059.html