P1081 开车旅行
输入样例#2: 复制
10 4 5 6 1 2 3 7 8 9 10 7 10 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 7 10 7
输出样例#2: 复制
View Code
2 3 2 2 4 2 1 2 4 5 1 5 1 2 1 2 0 0 0 0 0
题解:一道不可做的题;代码+思维
双向链表,倍增维护次大值最大值
https://www.luogu.org/problemnew/solution/P1081
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M = 1e5 + 5, P = 19; struct edge{int l, r;}lnk[M]; struct node{ int id, h; bool operator < (const node &rhs) const{ return h < rhs.h; } }p[M]; int rnk[M], nxta[M], nxtb[M], A, B, stA[M][P+1], stB[M][P+1], f[M][P+1]; inline bool dir(int t){ if(!lnk[t].l)return 0; if(!lnk[t].r)return 1; if(p[t].h - p[lnk[t].l].h <= p[lnk[t].r].h - p[t].h)return 1; return 0; } inline int pd(int t, int a, int b){ if(!a || !b)return p[a + b].id; if(p[t].h - p[a].h <= p[b].h - p[t].h) return p[a].id; return p[b].id; } inline int ab(int a, int b){return a >= b ? a - b : b - a;} void drive(int st, int lim){ A = 0, B = 0; int tmp = lim; for(int o = P; o >= 0; o--) if(f[st][o] && (long long) A + B + stA[st][o] + stB[st][o] <= tmp) A += stA[st][o], B += stB[st][o], st = f[st][o]; if(nxta[st] && A + B + stA[st][0] <= tmp) A += stA[st][0]; } int read(){ int x = 0; int f = 1; char c = getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();} return x*=f; } int main(){ int n; scanf("%d", &n); for(int i = 1; i <= n; i++) p[i].h = read(), p[i].id = i; sort(p + 1, p + 1 + n); for(int i = 1; i <= n; i++) rnk[p[i].id] = i; for(int i = 1; i <= n; i++) lnk[i].l = i - 1, lnk[i].r = i + 1; lnk[1].l = 0, lnk[n].r = 0; for(int i = 1; i <= n; i++) { int t = rnk[i]; bool fg = dir(t); if(fg) nxtb[i] = p[lnk[t].l].id, nxta[i] = pd(t, lnk[lnk[t].l].l, lnk[t].r); else nxtb[i] = p[lnk[t].r].id, nxta[i] = pd(t, lnk[t].l, lnk[lnk[t].r].r); if(lnk[t].r) lnk[lnk[t].r].l = lnk[t].l; if(lnk[t].l) lnk[lnk[t].l].r = lnk[t].r; } for(int i = 1; i <= n; i++){ f[i][0] = nxtb[nxta[i]]; stA[i][0] = ab(p[rnk[nxta[i]]].h, p[rnk[i]].h); stB[i][0] = ab(p[rnk[f[i][0]]].h, p[rnk[nxta[i]]].h); } for(int o = 1; o <= P; o++) for(int i = n; i; i--){ f[i][o] = f[f[i][o-1]][o-1]; stA[i][o] = stA[i][o-1] + stA[f[i][o-1]][o-1]; stB[i][o] = stB[i][o-1] + stB[f[i][o-1]][o-1]; } int X0 = read(); double tmp = 2e9; int id = -1; for(int i = 1; i <= n; i++){ drive(i, X0); if(B && 1.0*A/B < tmp){ tmp = 1.0*A/B; id = i; } else if(B && 1.0*A/B == tmp && rnk[i] > rnk[id]) id = i; } printf("%d ",id); int m = read(); while(m--){ int st = read(), x = read(); drive(st, x); printf("%d %d ", A, B); } }