vijos 1780 开车旅行
Posted ziliuziliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vijos 1780 开车旅行相关的知识,希望对你有一定的参考价值。
细节巨多。
倍增即可。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> #include<cmath> #include<cstdlib> #define maxv 200500 #define maxn 100500 #define eps 1e-7 #define inf 0x7f7f7f7f7f7f7f7fLL using namespace std; long long n,m,h[maxn],x,y,aft[maxn][3],anc[maxv][20],dis1[maxv][20],dis2[maxv][20],hashed[maxn],pos[maxn]; long long ret1=0,ret2=0,ans; struct pnt { long long ret,dot,rets; }p[5]; set <long long> s; set <long long> ::iterator it; double ans1=inf; bool cmp(pnt x,pnt y) { if (x.ret!=y.ret) return x.ret<y.ret; return x.rets>y.rets; } void divide() { for (long long i=1;i<=n;i++) hashed[i]=h[i]; sort(hashed+1,hashed+n+1); for (long long i=1;i<=n;i++) { h[i]=lower_bound(hashed+1,hashed+n+1,h[i])-hashed; pos[h[i]]=i; } } long long ask(long long x,long long y) { ret1=0;ret2=0; for (long long e=19;e>=0;e--) { if ((ret1+ret2+dis1[x][e]+dis2[x][e]<=y) && (anc[x][e])) { ret1+=dis1[x][e];ret2+=dis2[x][e]; x=anc[x][e]; } } } void update(long long x) { if (!ret1) return; if ((double)ret2/ret1<ans1) {ans1=(double)ret2/ret1;ans=x;} else if (((double)ret2/ret1-ans1<=eps) && (hashed[h[ans]]<hashed[h[x]])) ans=x; } int main() { scanf("%lld",&n); for (long long i=1;i<=n;i++) scanf("%lld",&h[i]); divide(); for (long long i=n;i>=1;i--) { for (long long j=1;j<=4;j++) p[j].dot=p[j].ret=inf; it=s.lower_bound(h[i]); if (it!=s.end()) { p[3].ret=hashed[h[pos[*it]]];p[3].dot=pos[*it]; if (++it!=s.end()) {p[4].ret=hashed[h[pos[*it]]];p[4].dot=pos[*it];} it--; } if (it!=s.begin()) { it--; p[1].ret=hashed[h[pos[*it]]];p[1].dot=pos[*it]; if (it!=s.begin()) {it--;p[2].ret=hashed[h[pos[*it]]];p[2].dot=pos[*it];it++;} } for (int j=1;j<=4;j++) { if (p[j].ret!=inf) { p[j].rets=hashed[h[i]]-p[j].ret; p[j].ret=abs(hashed[h[i]]-p[j].ret); } } sort(p+1,p+5,cmp); if (p[1].ret!=inf) aft[i][1]=p[1].dot; if (p[2].ret!=inf) aft[i][2]=p[2].dot; s.insert(h[i]); } for (long long i=1;i<=n;i++) { anc[2*i-1][0]=2*aft[i][1];dis1[2*i-1][0]=abs(hashed[h[aft[i][1]]]-hashed[h[i]]);dis2[2*i-1][0]=0; anc[2*i][0]=max(2*aft[i][2]-1,(long long)0);dis1[2*i][0]=0;dis2[2*i][0]=abs(hashed[h[aft[i][2]]]-hashed[h[i]]); } n*=2; for (long long e=1;e<=19;e++) for (long long i=1;i<=n;i++) { anc[i][e]=anc[anc[i][e-1]][e-1]; dis1[i][e]=dis1[i][e-1]+dis1[anc[i][e-1]][e-1]; dis2[i][e]=dis2[i][e-1]+dis2[anc[i][e-1]][e-1]; } scanf("%lld",&x); for (long long i=2;i<=n;i+=2) {ask(i,x);update(i/2);} printf("%d\n",ans); scanf("%lld",&m); for (long long i=1;i<=m;i++) { scanf("%lld%lld",&x,&y); ask(2*x,y); printf("%lld %lld\n",ret2,ret1); } return 0; }
以上是关于vijos 1780 开车旅行的主要内容,如果未能解决你的问题,请参考以下文章