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 开车旅行的主要内容,如果未能解决你的问题,请参考以下文章