vijos 1780 开车旅行

细节巨多。

倍增即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<cmath>
#include<cstdlib>
#define maxv 200500
#define maxn 100500
#define eps 1e-7
#define inf 0x7f7f7f7f7f7f7f7fLL
using namespace std;
long long n,m,h[maxn],x,y,aft[maxn][3],anc[maxv][20],dis1[maxv][20],dis2[maxv][20],hashed[maxn],pos[maxn];
long long ret1=0,ret2=0,ans;
struct pnt
{
    long long ret,dot,rets;
}p[5];
set <long long> s;
set <long long> ::iterator it;
double ans1=inf;
bool cmp(pnt x,pnt y)
{
    if (x.ret!=y.ret) return x.ret<y.ret;
    return x.rets>y.rets;
}
void divide()
{
    for (long long i=1;i<=n;i++) hashed[i]=h[i];
    sort(hashed+1,hashed+n+1);
    for (long long i=1;i<=n;i++)
    {
        h[i]=lower_bound(hashed+1,hashed+n+1,h[i])-hashed;
        pos[h[i]]=i;
    }
}
long long ask(long long x,long long y)
{
    ret1=0;ret2=0;
    for (long long e=19;e>=0;e--)
    {
        if ((ret1+ret2+dis1[x][e]+dis2[x][e]<=y) && (anc[x][e]))
        {
            ret1+=dis1[x][e];ret2+=dis2[x][e];
            x=anc[x][e];
        }
    }
}
void update(long long x)
{
    if (!ret1) return;
    if ((double)ret2/ret1<ans1) {ans1=(double)ret2/ret1;ans=x;}
    else if (((double)ret2/ret1-ans1<=eps) && (hashed[h[ans]]<hashed[h[x]])) ans=x;
}
int main()
{
    scanf("%lld",&n);
    for (long long i=1;i<=n;i++) scanf("%lld",&h[i]);
    divide();
    for (long long i=n;i>=1;i--)
    {
        for (long long j=1;j<=4;j++) p[j].dot=p[j].ret=inf;
        it=s.lower_bound(h[i]);
        if (it!=s.end())
        {
            p[3].ret=hashed[h[pos[*it]]];p[3].dot=pos[*it];
            if (++it!=s.end()) {p[4].ret=hashed[h[pos[*it]]];p[4].dot=pos[*it];}
            it--;
        }
        if (it!=s.begin())
        {
            it--;
            p[1].ret=hashed[h[pos[*it]]];p[1].dot=pos[*it];
            if (it!=s.begin()) {it--;p[2].ret=hashed[h[pos[*it]]];p[2].dot=pos[*it];it++;}
        }
        for (int j=1;j<=4;j++)
        {
            if (p[j].ret!=inf)
            {
                p[j].rets=hashed[h[i]]-p[j].ret;
                p[j].ret=abs(hashed[h[i]]-p[j].ret);
            }
        }
        sort(p+1,p+5,cmp);
        if (p[1].ret!=inf) aft[i][1]=p[1].dot;
        if (p[2].ret!=inf) aft[i][2]=p[2].dot;
        s.insert(h[i]);
    }
    for (long long i=1;i<=n;i++)
    {
        anc[2*i-1][0]=2*aft[i][1];dis1[2*i-1][0]=abs(hashed[h[aft[i][1]]]-hashed[h[i]]);dis2[2*i-1][0]=0;
        anc[2*i][0]=max(2*aft[i][2]-1,(long long)0);dis1[2*i][0]=0;dis2[2*i][0]=abs(hashed[h[aft[i][2]]]-hashed[h[i]]);
    }
    n*=2;
    for (long long e=1;e<=19;e++)
        for (long long i=1;i<=n;i++)
        {
            anc[i][e]=anc[anc[i][e-1]][e-1];
            dis1[i][e]=dis1[i][e-1]+dis1[anc[i][e-1]][e-1];
            dis2[i][e]=dis2[i][e-1]+dis2[anc[i][e-1]][e-1];
        }
    scanf("%lld",&x);
    for (long long i=2;i<=n;i+=2)
        {ask(i,x);update(i/2);}
    printf("%d\n",ans);
    scanf("%lld",&m);
    for (long long i=1;i<=m;i++)
    {
        scanf("%lld%lld",&x,&y);
        ask(2*x,y);
        printf("%lld %lld\n",ret2,ret1);
    }
    return 0;
}
时间: 2024-12-18 10:48:42

vijos 1780 开车旅行的相关文章

洛谷P1081 开车旅行

P1081 开车旅行 152通过 524提交 题目提供者洛谷OnlineJudge 标签倍增NOIp提高组2012 难度省选/NOI- 提交该题 讨论 题解 记录 最新讨论 我前排提醒一下 题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi−

noip2012 开车旅行

P1081 开车旅行 139通过 484提交 题目提供者洛谷OnlineJudge 标签倍增2012NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录 题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi− Hj|. 旅行过程中,小

codevs 1199 开车旅行 2012年NOIP全国联赛提高组

1199 开车旅行 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i的海拔高度为Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即d[i, j] = |Hi − Hj|. 旅行过程中,小A 和小B轮流开

2012Noip提高组Day1 T3 开车旅行

题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi− Hj|. 旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次.他们计划 选择一个城市 S 作为起点,一直向东行驶,并且最多行驶 X 公里就结束旅行.小 A 和小 B

开车旅行

洛谷P1081 开车旅行  NOIP 2012 提高组 第一天 第三题 题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即 d[i,j] = |Hi− Hj|. 旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次.他们计划 选择一个城市 S 作

【题解】开车旅行

开车旅行 (drive.cpp/c/pas) [问题描述] 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i的海拔高度为Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即d[i, j] = |???? − ????|. 旅行过程中,小A 和小B轮流开车,第一天小A 开车,之后每天轮换一次.他们计划选择一个城市 S 作为起点,一直向东行驶,并且最多行驶 X

习题:开车旅行(倍增+预处理)

开车旅行(NOIP提高组2012) [描述]小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市i 的海拔高度为Hi,城市i 和城市j 之间的距离d[i,j]恰好是这两个城市海拔高度之差的绝对值,即d[i,j] = |Hi - Hj|.旅行过程中,小A和小B轮流开车,第一天小A开车,之后每天轮换一次.他们计划选择一个城市S作为起点,一直向东行驶,并且最多行驶X公里就结束旅行.小A和小B的驾驶风格不同,小B总是

题解 P1081 【开车旅行】

Solution 开车旅行 题目大意:有\(n\)座城市,每座城市有一个海拔高度,你只能从编号小的往编号大的移动.定义两城市距离为海拔高度差的绝对值.小A开车会去离他第二近的城市,小B开车会去离他最近的城市.(如果距离相同则认为海拔低的近).两人开车的距离之和不能超过\(X\),问给定一个\(X\)从哪座城市出发小A小B行驶距离之比最小,(一样小的认为海拔高的小),问给定出发点\(s\)和\(X\),小A小B分别行驶距离 倍增 分析:首先关键在于给定\(s\)和\(X\)的时候快速算出他俩分别走

【noip2012】开车旅行 [倍增]

开车旅行 倍增 详细版 可以发现每个起点出发后面选择的城市都是一定的 所以预处理出\(to[i][j],da[i][j],db[i][j]\)表示从\(i\)出发小\(A\)和小\(B\)经过\(2^j\)轮后到达的地点.小\(A\)走的路程.小\(B\)走的路程 预处理时询问第一近和第二近的地点用双向链表 双向链表 不仅记录当前元素的下一个元素\((next)\)还记录当前元素的上一个元素\((pre)\) 数组版: int head,tail,tot; struct Node{ int va