思路
线段树好题,仔细读题后注意到只有 7 7 7种情况,因为只要确定第一个数是星期几,后面所有的数都确定了,这是对于正向的情况,对于反向走的情况,因为题目的条件本身就是对称的,即 1 → 7 1\rightarrow 7 1→7 等价于 7 → 1 7\rightarrow 1 7→1,所以反向将 l , r l,r l,r交换下,然后确定是第几种情况即可。
最后就是开 7 7 7个线段树维护区间最小,最大值,区间右最大值-左最小值,区间左最大值-右最小值即可。
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
// Problem: Traveling Merchant
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/13168/L
// Memory Limit: 524288 MB
// Time Limit: 4000 ms
// Date: 2021-03-21 21:26:01
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
#define lx x<<1
#define rx x<<1|1
struct node{
int l,r;
int mx,mn;
int l_r,r_l;
}a[8][N<<2];
void re(int x,int id){
a[id][x].mx=max(a[id][lx].mx,a[id][rx].mx);
a[id][x].mn=min(a[id][lx].mn,a[id][rx].mn);
a[id][x].l_r=max({a[id][lx].l_r,a[id][rx].l_r,a[id][rx].mx-a[id][lx].mn});
a[id][x].r_l=max({a[id][lx].r_l,a[id][rx].r_l,a[id][lx].mx-a[id][rx].mn});
}
void upd(node &a,node b){
a.l_r=max(a.l_r,max(b.l_r,b.mx-a.mn));
a.r_l=max(a.r_l,max(b.r_l,a.mx-b.mn));
a.mx=max(a.mx,b.mx);
a.mn=min(a.mn,b.mn);
}
int b[8][N];
void build(int x,int l,int r,int id){
a[id][x].l=l,a[id][x].r=r;
if(l==r){
a[id][x].mx=a[id][x].mn=b[id][l];
return;
}
int m=(l+r)>>1;
build(lx,l,m,id);
build(rx,m+1,r,id);
re(x,id);
}
node query(int x,int l,int r,int id){
if(l<=a[id][x].l&&a[id][x].r<=r) return a[id][x];
node ans;
int m=(a[id][x].l+a[id][x].r)>>1;
if(r<=m) ans=query(lx,l,r,id);
else if(l>m) ans=query(rx,l,r,id);
else {
ans=query(lx,l,r,id);
node ans1=query(rx,l,r,id);
upd(ans,ans1);
}
return ans;
}
int n;
int d[N],v[N];
int main(){
scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&d[i]);
for(int id=1;id<=7;id++){
int c=0,f=1;
for(int i=id;i<=n;i++){
b[id][i]=v[i]+d[i]*c;
c+=f;
if(c==3) f=-1;
if(c==0) f++;
}
c=0,f=1;
for(int i=id-1;i;i--){
b[id][i]=v[i]+d[i]*c;
c+=f;
if(c==3) f=-1;
if(c==0) f++;
}
build(1,1,n,id);
}
int q;scanf("%d",&q);while(q--){
int l,r;scanf("%d%d",&l,&r);
int id;
if(l<=r){
id=l%7;
if(!id) id=7;
printf("%d\n",max(0,query(1,l,r,id).l_r));
}
else {
swap(l,r);
id=r%7+1;
printf("%d\n",max(0,query(1,l,r,id).r_l));
}
}
return 0;
}