P1081 开车旅行

Posted sfwr-you

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 nodeint 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;
    

 

以上是关于P1081 开车旅行的主要内容,如果未能解决你的问题,请参考以下文章

题解 P1081 开车旅行

Luogu P1081 NOIP2012开车旅行

[NOIP2012] 提高组 洛谷P1081 开车旅行

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

P1081 开车旅行

开车旅行