codeforces 292 div2 E【RE】

博客讲述了作者在解决codeforces上的一个编程问题,涉及猴子Drazil在公园中避开儿童玩耍区域进行早晨跑步以消耗最大能量的算法。问题包括计算不同选择对能量的影响,以及在不同数据规模下算法的表现和遇到的运行错误(RE)。

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

。。。。。。。(⊙v⊙)嗯。。。。。。。。。狂RE表示查不出来哪里错了。。。。。

然后方法应该是bingo了。。。。。。

题目:

E. Drazil and Park
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

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 yis 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 ≤ 1051 ≤ 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.

这是之前的代码,但是显然是T掉了,复杂度大约是n^2,用的是双指针。

#include <stdio.h>
#define ll long long
#define maxn 100100
ll road[maxn],d[maxn],h[maxn];
int n,m;
ll dis(int r,int l)
{
    if(road[r]<road[l])
    {//printf("return %lld %lld %lld \n",road[n-1]-road[l],d[n-1],road[r]);
        return road[n-1]-road[l]+d[n-1]+road[r];
    }
    return road[r]-road[l];
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int i,j,k;
        road[0]=0;
        for(i=0;i<n;i++)
        {
            scanf("%lld",&d[i]);
            road[i+1]=road[i]+d[i];
        }
        for(i=0;i<n;i++)
        {
            scanf("%lld",&h[i]);
        }
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&j,&k);
            int l=k%n,r=(j-2)%n;
            if(r<0) r+=n;
            int llt=l,rr=(l+1);
            ll ans=(h[rr%n]+h[llt])*2+dis(rr%n,llt);//oad[rr]-road[ll];
          //  printf("dis=%lld\n",dis(rr%n,llt));
            int st=rr+1;
            rr%=n;
            if(r<l) r+=n;
            while(st<=r)
            {
                ll ans1=(h[st%n]+h[llt])*2+dis(st%n,llt);//road[st]-road[ll];
                ll ans2=(h[st%n]+h[rr])*2+dis(st%n,rr);//road[st]-road[rr];
                ll aa=ans1>ans2?ans1:ans2;
                if(aa>ans)
                {if(aa==ans1)
                {
                    rr=st%n;ans=aa;
                }
                else {llt=rr;rr=st%n;ans=aa;}
                }
                st++;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}
这是线段树的。线段树之前有想过,但是想了一会儿不知道怎么用线段做。。。。。RE之代码。。。。!!!!QAQ

差不多开了三棵树.

比如说查询区间[l,r],对于a[]保存的是l得值,b[]保存的是r的值,

每次查询的时候,查询sum[]和区间内左右a[].b[]的最大值之和,因为可能出现被单独隔离的区间,则需要再比较a[],b[]的值。。。感觉讲的毫不清楚啊。。。。

恩。。。当n小得时候结果都是对的,但是大得时候就是RE了,,,不知道这个空间应该怎么开了,我觉得明明是开的很大了!!!!!

#include <stdio.h>
#define _ll long long
#define maxn 200010

_ll a[maxn<<2],b[maxn<<2],sum[maxn<<2];
_ll n,m;
_ll h[maxn<<2],d[maxn<<2];
_ll max(_ll x,_ll y){return x>y?x:y;}
struct node
{
    _ll lm,rm,ma;
};
void create(_ll l,_ll r,_ll rt)
{
    sum[rt]=0;a[rt]=0,b[rt]=0;
    if(l==r)
    {
        a[rt]=2*h[l]+d[l];  //存储右边界的值
        b[rt]=2*h[l]-d[l];  //存储左边界的值
        sum[rt]=0;
        return;
    }
    _ll mid=(l+r)>>1;
    create(l,mid,rt<<1);create(mid+1,r,rt<<1|1);
    a[rt]=max(a[rt<<1],a[rt<<1|1]);
    b[rt]=max(b[rt<<1],b[rt<<1|1]);
    sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),a[rt<<1|1]+b[rt<<1]);

}
node query(_ll ll,_ll rr,_ll l,_ll r,_ll rt)
{
    if(ll==l&&rr==r)
    {
        node ret;
        ret.lm=b[rt],ret.rm=a[rt],ret.ma=sum[rt];

        return ret;
    }
    _ll mid=(l+r)>>1;
    node x,y,ret;
    if(rr<=mid)
    {
        return query(ll,rr,l,mid,rt<<1);
    }
    else if(ll>mid)
    {
        return query(ll,rr,mid+1,r,rt<<1|1);
    }
    else
    {
        x=query(ll,mid,l,mid,rt<<1);
        y=query(mid+1,rr,mid+1,r,rt<<1|1);
        ret.lm=max(y.lm,x.lm);ret.rm=max(x.rm,y.rm);
        ret.ma=max(max(x.ma,y.ma),x.lm+y.rm);

        return ret;
    }
}
int main()
{
    while(scanf("%lld%lld",&n,&m)!=EOF)
    {
        _ll i;
        _ll j;
        d[0]=0;
        for(i=0;i<n;i++)
        {
            scanf("%lld",&j);
            d[i+1]=d[i+1+n]=j;
        }
        for(i=0;i<n;i++)
        {
            scanf("%lld",&j);
            h[i]=h[i+n]=j;
        }
        for(i=1;i<n*n;i++)
        {
            d[i]+=d[i-1];
        }
        _ll len=n*2-1;
        create(0,len,1);
        while(m--)
        {
            _ll jj,kk;
            scanf("%lld%lld",&jj,&kk);
            jj--,kk--;
            int l=kk+1,r=jj-1;
            if(r<l) r+=n;
          //  printf("l=%d r=%d\n",l,r);
            node tmp=query(l,r,0,len,1);
            printf("%lld\n",tmp.ma);
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值