P1081 开车旅行

______________________________________________________________________________________________________________________

做法来自lyd书

双向链表初始化,倍增优化DP

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
long long la,lb;
int n,t,x0,ans,m;
struct node{int num,id;}h[101000];
int cmp(node x,node y)
{return x.num<y.num;}
int back[101000],to[101000],fw[101000];
int ga[101000],gb[101000],day[20][101000][2],da[20][101000][2],db[20][101000][2];
double minn=0x3f3f3f3f;
int d(int a,int b){return abs(h[a].num-h[b].num);}
void calc(int s,int x)
{
    int p=s;
    la=0;lb=0;
    for(int i=19;i>=0;i--)
    {
        if(day[i][p][0]&&(la+lb+da[i][p][0]+db[i][p][0]<=x))
        {
            la+=da[i][p][0];lb+=db[i][p][0];
            p=day[i][p][0];
        }
    }
    if(ga[p]&&la+lb+da[0][p][0]<=x)la+=da[0][p][0];
}
int pd(int a,int b,int j){
    if(!a) return h[b].id;
    if(!b) return h[a].id;
    if(h[j].num-h[a].num <= h[b].num-h[j].num) return h[a].id;
    return h[b].id;
}
bool zuo(int l,int r,int j){
    if(!l) return 0;
    if(!r) return 1;
    return h[j].num-h[l].num<=h[r].num-h[j].num;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {cin>>h[i].num;h[i].id=i;}
    sort(h+1,h+1+n,cmp);
    for(int i=1;i<=n;i++){back[i]=i-1;to[i]=i+1;fw[h[i].id]=i;}
    to[n]=0;
    for(int i=1;i<=n;i++)
    {
        int pos=fw[i],l=back[pos],r=to[pos];
        if(zuo(l,r,pos))
        {gb[i]=h[l].id;ga[i]=pd(back[l],r,pos);}
        else
        {gb[i]=h[r].id;ga[i]=pd(l,to[r],pos);}
        if(r)back[r]=l;
        if(l)to[l]=r;
    }
    for(int i=1;i<=n;i++){day[0][i][0]=ga[i];day[0][i][1]=gb[i];}
    for(int j=1;j<=n;j++)for(int k=0;k<=1;k++)day[1][j][k]=day[0][day[0][j][k]][1-k];
    for(int i=2;i<=19;i++)for(int j=1;j<=n;j++)for(int k=0;k<=1;k++)
    day[i][j][k]=day[i-1][day[i-1][j][k]][k];
    for(int i=1;i<=n;i++)
    {da[0][i][0]=d(fw[i],fw[ga[i]]);db[0][i][1]=d(fw[i],fw[gb[i]]);}
    for(int j=1;j<=n;j++)for(int k=0;k<=1;k++)
    {
        da[1][j][k]=da[0][j][k]+da[0][day[0][j][k]][1-k];
        db[1][j][k]=db[0][j][k]+db[0][day[0][j][k]][1-k];
    }
    for(int i=2;i<=19;i++)for(int j=1;j<=n;j++)for(int k=0;k<=1;k++)
    {
        da[i][j][k]=da[i-1][j][k]+da[i-1][day[i-1][j][k]][k];
        db[i][j][k]=db[i-1][j][k]+db[i-1][day[i-1][j][k]][k];
    }
    cin>>x0;
    for(int i=1;i<=n;i++)
    {
        calc(i,x0);
        if(lb&&(1.0*la/lb)<minn)
        {
            ans=i;
            minn=1.0*la/lb;
        }
    }
    cout<<ans<<endl;
    cin>>m;
    while(m--)
    {
        int a,b;
        cin>>a>>b;
        calc(a,b);
        cout<<la<<" "<<lb<<endl;
    }
}

原文地址:https://www.cnblogs.com/SFWR-YOU/p/11223065.html

时间: 2024-10-11 17:16:56

P1081 开车旅行的相关文章

洛谷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 开车旅行

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

P1081 开车旅行(Not Finish)

https://www.luogu.org/problemnew/show/P1081 原文地址:https://www.cnblogs.com/mzg1805/p/10422175.html

P1081 开车旅行[倍增](毒瘤题)

其实就是个大模拟. 首先,根据题意,小A和小B从任意一个城市开始走,无论\(X\)如何,其路径是一定唯一的. 显然对于两问都可以想出一个\(O(n^2)\)的暴力,即直接一步一步地向右走. 首先,我们当然需要知道A,B在每个城市的下一步如何走,记\(nexta(i),nextb(i)\)为A,B在\(i\)处时,下一步走到的城市编号. 考虑如何高效(复杂度小于等于\(O(nlogn)\))维护两个\(next\). 显然不能直接维护每个城市与其后面的城市的差值,再好的数据结构也会到\(O(n^2

noip2012 开车旅行

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

开车旅行

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

题解 P1081 【开车旅行】

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

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