Traveling Merchant(线段树)

思路

线段树好题,仔细读题后注意到只有 7 7 7种情况,因为只要确定第一个数是星期几,后面所有的数都确定了,这是对于正向的情况,对于反向走的情况,因为题目的条件本身就是对称的,即 1 → 7 1\rightarrow 7 17 等价于 7 → 1 7\rightarrow 1 71,所以反向将 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;
}