题意:
现在有一条线,所有位置都有一种商品,每个商品的价格为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;
}