CF515E Drazil and Park

化简一下公式: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];
	//	printf("l=%lld r=%lld\n",T[k].l,T[k].r); 
		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)
{
//	printf("l=%lld r=%lld\n",l,r);
	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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值