[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;
}
posted @ 2021-04-28 10:16  zkdxl  阅读(41)  评论(0编辑  收藏  举报