開車旅行[巧妙的倍增][set]
阿新 • • 發佈:2018-11-04
對於找第一第二近,用set+lower_bound,預處理出nxt_A nxt_B 表示A,B下一步走到哪裡
然後倍增 , st_A[i][j] 表示從i往後2^j步A走了多少 B同理
nxt[i][j] 表示往後走2^j步的位置
類似lca那樣預處理就好了
//一直RE但對拍一小時後的偽AC程式碼 #include<bits/stdc++.h> #define N 500005 #define inf 0x3fffffff #define LL long long using namespace std; LL n,x0,m; LL a[N],h[N]; set<LL> S; LL nxt_A[N] , nxt_B[N] , H_A[N] , H_B[N]; LL nxt[N][20] , st_A[N][20] , st_B[N][20]; LL read(){ LL cnt=0,f=1;char ch=0; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar(); return cnt*f; } void getab(LL x,LL pos,LL &ans1,LL &ans2){ for(LL i=18;i>=0;i--){ if(st_A[pos][i] + st_B[pos][i] <= x && nxt[pos][i]){ ans1 += st_A[pos][i]; ans2 += st_B[pos][i]; x -= (st_A[pos][i] + st_B[pos][i]); pos = nxt[pos][i]; } } if(nxt_A[pos] && st_A[pos][0] <= x) ans1 += st_A[pos][0]; } int main(){ n=read(); for(LL i=1;i<=n;i++) a[i]=read(),h[a[i]]=i; S.insert(inf) , S.insert(-inf); S.insert(a[n]) , S.insert(a[n-1]); nxt_B[n-1] = n; for(LL i=n-2;i>=1;i--){ LL nxt = *S.lower_bound(a[i]); LL pre = *--S.lower_bound(a[i]); set<LL>::iterator it; it = S.lower_bound(nxt); if(*it!=inf) ++it; LL nxt_nxt = *it; it = S.lower_bound(pre); if(*it!=-inf) --it; LL pre_pre = *it; if(nxt_nxt-a[i] < a[i]-pre) nxt_A[i] = h[nxt_nxt] , nxt_B[i] = h[nxt]; else if(a[i]-pre_pre <= nxt-a[i]) nxt_A[i] = h[pre_pre] , nxt_B[i] = h[pre]; else if(nxt-a[i] < a[i]-pre) nxt_A[i] = h[pre] , nxt_B[i] = h[nxt]; else nxt_A[i] = h[nxt] , nxt_B[i] = h[pre]; S.insert(a[i]); } for(LL i=1;i<n;i++) nxt[i][0] = nxt_B[nxt_A[i]]; for(LL i=1;i<=n;i++){ if(nxt_A[i]) st_A[i][0] = H_A[i] = abs(a[nxt_A[i]] - a[i]); if(nxt_B[i]) H_B[i] = abs(a[nxt_B[i]] - a[i]); if(nxt[i][0]) st_B[i][0] = abs(a[nxt[i][0]] - a[nxt_A[i]]); } for(LL i=1;i<=18;i++) for(LL j=1;j<=n;j++){ nxt[j][i] = nxt[nxt[j][i-1]][i-1]; st_A[j][i] = st_A[j][i-1] + st_A[nxt[j][i-1]][i-1]; st_B[j][i] = st_B[j][i-1] + st_B[nxt[j][i-1]][i-1]; } x0=read(); LL u1=1,u2=0,H=0; LL ans=1; for(LL i=1;i<=n;i++){ LL f1=0,f2=0; getab(x0,i,f1,f2); if(!f2) continue; if(f2*u1 > f1*u2 || (f2*u1 == f1*u2 && a[i]>H)) u1=f1 , u2=f2 , H=a[i] , ans=i; } printf("%lld\n",ans); m=read(); while(m--){ LL s=read(),x=read(); LL f1=0,f2=0; getab(x,s,f1,f2); printf("%lld %lld\n",f1,f2); }return 0; }