[题目链接]
https://www.luogu.org/problemnew/show/P1081
[算法]
STL-set + 倍增 + DP
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 #define MAXLOG 20 typedef long long ll; struct info { ll height; ll id; friend bool operator < (info a,info b) { return a.height < b.height; } } a[MAXN]; ll i,j,n,T,ans,x0,si,xi; set< info > s; ll ga[MAXN],gb[MAXN]; ll x,y; ll f[MAXN][MAXLOG],da[MAXN][MAXLOG],db[MAXN][MAXLOG]; pair<ll,ll> tmp; inline bool cmp(info x,info y) { if (x.height != y.height) return x.height < y.height; else return a[x.id].height < a[y.id].height; } inline void get(ll id) { ll len = 0; set< info > :: iterator it; info tmp[10]; it = s.find(a[id]); if (it != s.begin()) { it--; tmp[++len] = (info){a[id].height - it -> height,it -> id}; if (it != s.begin()) { it--; tmp[++len] = (info){a[id].height - it -> height,it -> id}; it++; } it++; } it++; if (it != s.end()) { tmp[++len] = (info){it -> height - a[id].height,it -> id}; it++; if (it != s.end()) tmp[++len] = (info){it -> height - a[id].height,it -> id}; } sort(tmp+1,tmp+len+1,cmp); ga[id] = tmp[1].id; if (len == 1) return; gb[id] = tmp[2].id; } inline pair<ll,ll> ask(ll pos,ll d) { ll i; ll ans1 = 0,ans2 = 0; for (i = MAXLOG - 1; i >= 0; i--) { if (f[pos][i] && ans1 + ans2 + da[pos][i] + db[pos][i] <= d) { ans1 += da[pos][i]; ans2 += db[pos][i]; pos = f[pos][i]; } } if (gb[pos]) { if (ans1 + ans2 + abs(a[pos].height - a[gb[pos]].height) <= d) ans1 += abs(a[pos].height - a[gb[pos]].height); } return make_pair(ans1,ans2); } int main() { scanf("%lld",&n); for (i = 1; i <= n; i++) { scanf("%lld",&a[i].height); a[i].id = i; } for (i = n; i >= 1; i--) { s.insert(a[i]); if (i != n) get(i); } for (i = 1; i <= n; i++) { f[i][0] = ga[gb[i]]; if (gb[i]) da[i][0] = abs(a[i].height - a[gb[i]].height); if (gb[i] && ga[gb[i]]) db[i][0] = abs(a[gb[i]].height - a[ga[gb[i]]].height); } for (j = 1; j < MAXLOG; j++) { for (i = 1; i <= n; i++) { f[i][j] = f[f[i][j-1]][j-1]; da[i][j] = da[i][j-1] + da[f[i][j-1]][j-1]; db[i][j] = db[i][j-1] + db[f[i][j-1]][j-1]; } } scanf("%lld",&x0); ans = 0; x = y = 0; for (i = 1; i <= n; i++) { tmp = ask(i,x0); if (tmp.second != 0 && (!ans || tmp.first * y < tmp.second * x)) { ans = i; x = tmp.first; y = tmp.second; } } printf("%lld ",ans); scanf("%lld",&T); while (T--) { scanf("%lld%lld",&si,&xi); tmp = ask(si,xi); printf("%lld %lld ",tmp.first,tmp.second); } return 0; }