欢迎来到SFWR的博客

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;
    }
}

 

posted @ 2019-07-21 22:16  SFWR  Views(137)  Comments(0Edit  收藏  举报