Codeforces Round #292 (Div. 1) C. Drazil and Park 线段树

在本篇博客中,我们探讨了一个有趣的算法问题——如何帮助猴子Drazil在避开儿童玩耍区域的同时选择两棵树进行晨跑以消耗最多能量。通过巧妙地拆解距离公式并运用线段树数据结构进行区间查询,我们实现了高效的算法解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C. Drazil and Park

题目连接:

http://codeforces.com/contest/516/problem/C

Description

Drazil is a monkey. He lives in a circular park. There are n trees around the park. The distance between the i-th tree and (i + 1)-st trees is di, the distance between the n-th tree and the first tree is dn. The height of the i-th tree is hi.

Drazil starts each day with the morning run. The morning run consists of the following steps:

Drazil chooses two different trees
He starts with climbing up the first tree
Then he climbs down the first tree, runs around the park (in one of two possible directions) to the second tree, and climbs on it
Then he finally climbs down the second tree.
But there are always children playing around some consecutive trees. Drazil can't stand children, so he can't choose the trees close to children. He even can't stay close to those trees.

If the two trees Drazil chooses are x-th and y-th, we can estimate the energy the morning run takes to him as 2(hx + hy) + dist(x, y). Since there are children on exactly one of two arcs connecting x and y, the distance dist(x, y) between trees x and y is uniquely defined.

Now, you know that on the i-th day children play between ai-th tree and bi-th tree. More formally, if ai ≤ bi, children play around the trees with indices from range [ai, bi], otherwise they play around the trees with indices from .

Please help Drazil to determine which two trees he should choose in order to consume the most energy (since he wants to become fit and cool-looking monkey) and report the resulting amount of energy for each day.

Input

The first line contains two integer n and m (3 ≤ n ≤ 105, 1 ≤ m ≤ 105), denoting number of trees and number of days, respectively.

The second line contains n integers d1, d2, ..., dn (1 ≤ di ≤ 109), the distances between consecutive trees.

The third line contains n integers h1, h2, ..., hn (1 ≤ hi ≤ 109), the heights of trees.

Each of following m lines contains two integers ai and bi (1 ≤ ai, bi ≤ n) describing each new day. There are always at least two different trees Drazil can choose that are not affected by children.

Output

For each day print the answer in a separate line.

Sample Input

5 3
2 2 2 2 2
3 5 2 1 4
1 3
2 2
4 5

Sample Output

12
16
18

Hint

题意

m个询问,问你区间[L,R]中h[a]2+h[b]2+dis(a,b)的最大值是多少。

要求a>b

题解

把dis(a,b)拆开成pred[a]-pred[b]

然后我令A = h[a]+pred[a],B = h[b]-pred[b]

那么询问就是问区间A+B的最大值,但是A得大于B。

所以线段树合并的时候注意一下就好了。


#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
const long long inf = 1LL*1e17;
long long h[maxn],d[maxn];
int n,q,a,b;
struct node{
    int l,r;
    long long A,B,AB;
}tree[maxn*4];
void build(int x,int l,int r){
    tree[x].l=l,tree[x].r=r;
    if(l==r){
        tree[x].A=h[l]+d[l-1];
        tree[x].B=h[l]-d[l-1];
        tree[x].AB=-inf;
    }else{
        int mid=(l+r)/2;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
        tree[x].A=max(tree[x<<1].A,tree[x<<1|1].A);
        tree[x].B=max(tree[x<<1].B,tree[x<<1|1].B);
        tree[x].AB=max(tree[x<<1].AB,max(tree[x<<1|1].AB,tree[x<<1].B+tree[x<<1|1].A));
    }
}
node query(int x,int l,int r){
    int L=tree[x].l,R=tree[x].r;
    if(l<=L&&R<=r){
        return tree[x];
    }
    int mid=(L+R)/2;
    node tmp1,tmp2,tmp3;
    tmp1.A=tmp1.B=tmp1.AB=tmp2.A=tmp2.B=tmp2.AB=tmp3.A=tmp3.B=tmp3.AB=-inf;
    if(l<=mid)tmp1=query(x<<1,l,r);
    if(r>mid)tmp2=query(x<<1|1,l,r);
    tmp3.A=max(tmp1.A,tmp2.A);
    tmp3.B=max(tmp1.B,tmp2.B);
    tmp3.AB=max(tmp1.AB,max(tmp2.AB,tmp1.B+tmp2.A));
    return tmp3;
}
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)scanf("%lld",&d[i]),d[n+i]=d[i];
    for(int i=1;i<=n;i++)scanf("%lld",&h[i]),h[i]*=2,h[n+i]=h[i];
    for(int i=1;i<=2*n;i++)d[i]+=d[i-1];
    build(1,1,2*n);
    for(int i=1;i<=q;i++){
        scanf("%d%d",&a,&b);
        if(a<=b)
            printf("%lld\n",query(1,b+1,a+n-1).AB);
        else printf("%lld\n",query(1,b+1,a-1).AB);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值