[CF515E] Drazil and Park
\(\text{Problem}:\)Drazil and Park
\(\text{Solution}:\)
先破环为链,根据给出的限制 \(a,b\) 确定查询区间 \([l,r]\)。
考虑处理出 \(d\) 的前缀和,则现在两个点的答案为 \(d_{y}-d_{x}+2(h_{x}+h_{y})\)。变换得到 \(d_{y}+2h_{y}-(d_{x}-2h_{x})\)。
分别维护 \(d_{i}+2h_{i}\) 的区间最大值和 \(d_{i}-2h_{i}\) 的区间最小值的下标即可。注意当查询到的位置相同时,需要特殊考虑。每次查询调用数据结构询问次数较多,故使用 \(\text{ST}\) 表维护。总时间复杂度 \(O(n\log n)\)。
\(\text{Code}:\)
#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=200010, M=20;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int n,m,Q,d[N],h[N],a[N];
int f1[N][M],f2[N][M],lg[N];
inline int S1(int x) { return d[x]+h[x]; }
inline int S2(int x) { return d[x]-h[x]; }
inline int Max(int x,int y)
{
return S1(x)>S1(y)?x:y;
}
inline int Min(int x,int y)
{
return S2(x)<S2(y)?x:y;
}
inline int Ask1(int x,int y)
{
int k=lg[y-x+1];
return Max(f1[x][k],f1[y-(1ll<<k)+1][k]);
}
inline int Ask2(int x,int y)
{
int k=lg[y-x+1];
return Min(f2[x][k],f2[y-(1ll<<k)+1][k]);
}
signed main()
{
lg[0]=-1;
for(ri int i=1;i<N;i++) lg[i]=lg[i>>1]+1;
n=read(), Q=read();
for(ri int i=1;i<=n;i++) d[i+1]=read();
for(ri int i=1;i<=n;i++) h[i]=read()*2;
for(ri int i=1;i<=n;i++) h[i+n]=h[i];
for(ri int i=2;i<=n;i++) d[i+n]=d[i];
m=n+n;
for(ri int i=1;i<=m;i++) d[i]+=d[i-1];
for(ri int i=1;i<=m;i++) f1[i][0]=f2[i][0]=i;
for(ri int i=1;(1ll<<i)<=m;i++)
for(ri int j=1;j+(1ll<<i)-1<=m;j++)
f1[j][i]=Max(f1[j][i-1],f1[j+(1ll<<(i-1))][i-1]),
f2[j][i]=Min(f2[j][i-1],f2[j+(1ll<<(i-1))][i-1]);
for(ri int i=1;i<=Q;i++)
{
int l,r;
l=read(), r=read();
int p,q;
if(l<=r)
{
p=r+1, q=l+n-1;
int g1=Ask1(p,q), g2=Ask2(p,q);
if(g1^g2) printf("%lld\n",S1(g1)-S2(g2)+(g1<g2)*(d[g2]-d[g1]));
else
{
int res=-1e18;
if(g1>p)
{
int ss=Ask1(p,g1-1);
res=max(res,S1(ss)-S2(g1)+(ss<g1)*(d[g1]-d[ss]));
ss=Ask2(p,g1-1);
res=max(res,S1(g1)-S2(ss)+(g1<ss)*(d[ss]-d[g1]));
}
if(g1<q)
{
int ss=Ask1(g1+1,q);
res=max(res,S1(ss)-S2(g1)+(ss<g1)*(d[g1]-d[ss]));
ss=Ask2(g1+1,q);
res=max(res,S1(g1)-S2(ss)+(g1<ss)*(d[ss]-d[g1]));
}
printf("%lld\n",res);
}
}
else
{
p=r+1, q=l-1;
int g1=Ask1(p,q), g2=Ask2(p,q);
if(g1^g2) printf("%lld\n",S1(g1)-S2(g2)+(g1<g2)*(d[g2]-d[g1]));
else
{
int res=-1e18;
if(g1>p)
{
int ss=Ask1(p,g1-1);
res=max(res,S1(ss)-S2(g1)+(ss<g1)*(d[g1]-d[ss]));
ss=Ask2(p,g1-1);
res=max(res,S1(g1)-S2(ss)+(g1<ss)*(d[ss]-d[g1]));
}
if(g1<q)
{
int ss=Ask1(g1+1,q);
res=max(res,S1(ss)-S2(g1)+(ss<g1)*(d[g1]-d[ss]));
ss=Ask2(g1+1,q);
res=max(res,S1(g1)-S2(ss)+(g1<ss)*(d[ss]-d[g1]));
}
printf("%lld\n",res);
}
}
}
return 0;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。