【正经题解】开车旅行
2024-02-23 11:10:13
发布于:浙江
12阅读
0回复
0点赞
思路就是倍增, 然而预处理就挺麻烦的, 要用 离散化 加 双向链表 处理出每一个点 和 要到的下一个点。
这里的处理要用到一些技巧, 详见代码。
然后就是倍增:
[ ][ ] 表示 从第 个点出发, 和 没人开了( )天所到的点, ( )表示 ( ) 的 路程。
因为 是先走的, 所以要看最后一步 还能不能再走一步。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n, m, l, r, j;
struct node{
int i, v, l, r;
bool operator < (const node & A) const{
return v < A.v;
}
}d[100005];
int h[100005], p[100005];
int stA[100005][21], stB[100005][21], f[100005][21];
int na[100005], nb[100005], a, b, ans = n;
double minn = 2147483647;
bool zuo(){
if(!l) return 0;
if(!r) return 1;
return d[j].v-d[l].v<=d[r].v-d[j].v;
}
int pd(int a, int b){
if(!a) return d[b].i;
if(!b) return d[a].i;
if(d[j].v-d[a].v <= d[b].v-d[j].v) return d[a].i;
return d[b].i;
}
void make_st(){
int i, j;
for(j = 1; j <= 19; j++){
for(i = 1; i <= n; i++){
f[i][j] = f[f[i][j-1]][j-1];
stA[i][j] = stA[i][j-1] + stA[f[i][j-1]][j-1];
stB[i][j] = stB[i][j-1] + stB[f[i][j-1]][j-1];
}
}
}
void getab(long long x, int p){
int i, j;
a = b = 0;
for(i = 19; i >= 0; i--){
if(f[p][i] && (long long)(a + b + stA[p][i]+stB[p][i]) <= x){
a += stA[p][i];
b += stB[p][i];
p = f[p][i];
}
}
if(na[p] && a + b + stA[p][0] <= x) a += stA[p][0];
}
int main(){
int i;
long long x;
scanf("%d", &n);
for(i = 1; i <= n; i++) scanf("%d", &d[i].v);
for(i = 1; i <= n; i++) d[i].i = i;
sort(d+1, d+i);
for(i = 1; i <= n; i++) p[d[i].i] = i;
for(i = 1; i <= n; i++) d[i].l = i-1, d[i].r = i+1;
d[1].l = d[n].r = 0;
for(i = 1; i <= n; i++){
j = p[i]; l = d[j].l; r = d[j].r;
if(zuo()) nb[i] = d[l].i, na[i] = pd(d[l].l, r);//左边的近
else nb[i] = d[r].i, na[i] = pd(l, d[r].r);//右边的近
if(l) d[l].r = r;//用完j要把j删除掉
if(r) d[r].l = l;
}
for(i = 1; i <= n; i++){
f[i][0] = nb[na[i]];
stA[i][0] = abs(d[p[i]].v - d[p[na[i]]].v);
stB[i][0] = abs(d[p[f[i][0]]].v - d[p[na[i]]].v);//记住结构体已经排序了, 所以要用他们的排名获取信息
}
make_st();
scanf("%lld%d", &x, &m);
for(i = 1; i <= n; i++){
getab(x, i);
if(b && 1.0*a/b < minn){
minn = 1.0*a/b;
ans = i;
}
}
printf("%d\n", ans);
for(i = 1; i <= m; i++){
scanf("%d%lld", &j, &x);
getab(x, j);
printf("%d %d\n", a, b);
}
return 0;
}
这里空空如也
有帮助,赞一个