题目
有 n n n个城市,它们在卖同一种物品。每个城市这个物品的起始价 v [ i ] v[i] v[i],星期一和星期天加个为 v [ i ] v[i] v[i],星期二和星期六价格为 v [ i ] + d [ i ] v[i]+d[i] v[i]+d[i],星期三和星期五价格为 v [ i ] + 2 ∗ d [ i ] v[i]+2*d[i] v[i]+2∗d[i],星期四为 v [ i ] + 3 ∗ d [ i ] v[i]+3*d[i] v[i]+3∗d[i]。有一个人从 s s s城按顺序走到 t t t城,在过程中进行了一次买卖,求最多能赚多少。
思路
创建七个线段树,分别是反推回去的城市 1 1 1是星期几来决定的。
i d [ i ] [ j ] [ x ] id[i][j][x] id[i][j][x], i i i为现在是星期几, j j j为当前走到了哪里, x x x为现在是正方向还是反方向, i d [ i ] [ j ] [ x ] id[i][j][x] id[i][j][x]表示当前为星期 i i i,走到 j j j的时候反推回去第一天的星期数。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<ctime>
#include<iostream>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<iomanip>
#include<list>
#include<bitset>
#include<sstream>
#include<fstream>
#include<complex>
#include<algorithm>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#define int long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
int v[100010],d[100010],id[8][100010][2];
struct seg{
struct sut{
int l,r,mid,ma,mi,res;
}tree[400040];
#define ls x<<1
#define rs x<<1|1
int a[100100];
void merge(sut &ans,sut a,sut b){
ans.ma=max(a.ma,b.ma);
ans.mi=min(a.mi,b.mi);
ans.res=max(a.res,b.res);
ans.res=max(ans.res,b.ma-a.mi);
}
void build(int x,int l,int r){
tree[x]={l,r,(l+r)>>1,-INF,INF,-INF};
if(l==r){
tree[x].ma=tree[x].mi=a[l];
return;
}
int mid=tree[x].mid;
build(ls,l,mid);
build(rs,mid+1,r);
merge(tree[x],tree[ls],tree[rs]);
}
sut query(int x,int l,int r){
if(l<=tree[x].l&&tree[x].r<=r){
return tree[x];
}
int mid=tree[x].mid;
if(r<=mid) return query(ls,l,r);
else if(l>mid) return query(rs,l,r);
else{
sut ans;
merge(ans,query(ls,l,mid),query(rs,mid+1,r));
return ans;
}
return tree[x];
}
}rt[8][2];
int cal(int n,int v,int d){
if(n==1||n==7) return v;
if(n==2||n==6) return v+d;
if(n==3||n==5) return v+2*d;
return v+3*d;
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n;
cin>>n;
// cout<<"?"<<endl;
for(int i=1;i<=n;i++){
cin>>v[i]>>d[i];
}
// cout<<"~ 1"<<endl;
for(int i=1;i<=7;i++){
int now=i;
for(int j=1;j<=n;j++){
int k=cal(now,v[j],d[j]);
id[now][j][0]=i;
rt[i][0].a[j]=k;
now++;
now%=7;
if(now==0) now=7;
}
rt[i][0].build(1,1,n);
}
reverse(v+1,v+1+n);
reverse(d+1,d+1+n);
for(int i=1;i<=7;i++){
// cout<<i<<endl;
int now=i;
for(int j=1;j<=n;j++){
int k=cal(now,v[j],d[j]);
id[now][j][1]=i;
rt[i][1].a[j]=k;
now++;
now%=7;
if(now==0) now=7;
}
rt[i][1].build(1,1,n);
}
//cout<<"!"<<endl;
int q;
cin>>q;
while(q--){
int s,t;
cin>>s>>t;
int ans=0;
if(s<t){
int p=id[1][s][0];
ans=max(ans,rt[p][0].query(1,s,t).res);
}
else{
s=n-s+1;
t=n-t+1;
int p=id[1][s][1];
ans=max(ans,rt[p][1].query(1,s,t).res);
}
cout<<ans<<endl;
}
return 0;
}