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