化简一下公式:2h[a]+2h[b]+dis(a,b)=2h[a]+2h[b]+d[b]-d[a-1](d数组是一个距离前缀和)
对于我们要求的一个区间,需要找的就是max((2h[b]+d[b])+(2h[a]-d[a-1]))
而对于这个max,需要再维护一个最大左前缀和一个最大右后缀
是不是和gss1很像
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=6e5+5;
int n,m;
int d[N],h[N];
struct node{int l,r,max;}T[N<<2];
inline node pushup(node L,node R)
{
node res;
res.l=max(L.l,R.l);
res.r=max(R.r,L.r);
res.max=max(L.l+R.r,max(L.max,R.max));
return res;
}
void build(int k,int l,int r)
{
if (l==r)
{
T[k].max=0;
T[k].l=2*h[l]-d[l-1];
T[k].r=2*h[l]+d[l-1];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
node L,R;
L=T[k<<1]; R=T[k<<1|1];
T[k]=pushup(L,R);
}
node query(int k,int l,int r,int qx,int qy)
{
if (qx<=l && r<=qy) return T[k];
int mid=l+r>>1;
if (qx>mid) return query(k<<1|1,mid+1,r,qx,qy);
if (qy<=mid) return query(k<<1,l,mid,qx,qy);
node L,R;
L=query(k<<1,l,mid,qx,qy); R=query(k<<1|1,mid+1,r,qx,qy);
return pushup(L,R);
}
signed main(){
scanf("%lld%lld",&n,&m);
for (register int i=1; i<=n; ++i) scanf("%lld",&d[i]),d[i+n]=d[i];
for (register int i=1; i<=n; ++i) scanf("%lld",&h[i]),h[i+n]=h[i];
int len=n;
n<<=1;
for (register int i=1; i<=n; ++i) d[i]+=d[i-1];
build(1,1,n);
while (m--)
{
int x,y;
scanf("%lld%lld",&x,&y);
if (x<=y) printf("%lld\n",query(1,1,n,y+1,x+len-1).max);
else printf("%lld\n",query(1,1,n,y+1,x-1).max);
}
return 0;
}