- 2012
T3
- @ 2025-10-3 15:46:34
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long LL;
const int N = 1e5 + 20, P = 17;
const LL INF = 1e17;
int n, m;
int h[N];
int s[N], x[N];
int x0;
int f[P + 1][N][2], fa[P + 1][N][2], fb[P + 1][N][2];
struct City{
int id, w;
bool operator < (const City &W) const
{
return w < W.w;
}
};
multiset<City> q;
int A, B, ansid;
double ans = INF * 1.0;
void calc(int S, int X)
{
int p = S;
A = 0, B = 0;
for(int i = P - 1; i >= 0; i--) //二进制累加
{
if(f[i][p][0] && A + B + fa[i][p][0] + fb[i][p][0] <= X)
{
A += fa[i][p][0];
B += fb[i][p][0];
p = f[i][p][0];
}
}
}
void init()
{
q.insert({0, INF}), q.insert({0, INF + 1});
q.insert({0, -INF}), q.insert({0, -INF - 1});
for(int i = n; i > 0; i --)
{
int ca = 0, cb = 0, d1 = INF, d2 = INF;
City now = {i, h[i]};
vector<City> t;
auto qq = q.lower_bound(now); qq++;
for(int k = 0; k < 4; k++)
t.push_back(*qq), qq --;
for(int k = 3; k >= 0; k--)
{
int d = abs(h[i] - t[k].w);
if(d < d1)
{
d2 = d1, d1 = d;
ca = cb, cb = t[k].id;
}
else if(d < d2)
{
d2 = d;
ca = t[k].id;
}
}
f[0][i][0] = ca, f[0][i][1] = cb;
fa[0][i][0] = abs(h[i] - h[ca]);
fb[0][i][1] = abs(h[i] - h[cb]);
q.insert(now);
}
for(int i = 1; i <= P; i++)
for(int j = 1; j <= n; j++)
for(int k = 0; k < 2; k++)
{
if(i == 1)
{
f[1][j][k] = f[0][f[0][j][k]][k^1];
fa[1][j][k] = fa[0][j][k] + fa[0][f[0][j][k]][k^1];
fb[1][j][k] = fb[0][j][k] + fb[0][f[0][j][k]][k^1];
}
else
{
f[i][j][k] = f[i - 1][f[i - 1][j][k]][k];
fa[i][j][k] = fa[i - 1][j][k] + fa[i - 1][f[i - 1][j][k]][k];
fb[i][j][k] = fb[i - 1][j][k] + fb[i - 1][f[i - 1][j][k]][k];
}
}
}
signed main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> h[i];
init();
cin >> x0 >> m;
for(int i = 1; i <= m; i++)
cin >> s[i] >> x[i];
LL ansh = 0;
for(int i = 1; i<= n; i++)
{
calc(i, x0);
double as = B?(double)A/(double)B : INF;
if(as < ans || as == ans && ansh < h[i])
{
ansh = h[i]; //编号最大
ans = as;
ansid = i;
}
}
cout << ansid << endl;
for(int i = 1; i <= m; i++)
{
calc(s[i], x[i]);
cout << A << " " << B << endl;
}
return 0;
}
/*
对于小A和小B而言,任何一个城市都只能到达离此城市最近的两个城市。
在一个有序序列中,找到最接近这个点的值和第二接近这个点的值。
可以使用set来实现。
对于本问题,我们要计算哪些信息? 小A的开车行驶路程总数和小B开车行驶的路程总数。
问题1:枚举起点。
暴力计算显然是超时的,如何优化?
f[i][j][k]: 从城市j出发,行驶2^i天,k先开车,最终会到达城市
fa[i][j][k]: 从城市j出发,行驶2^i天,k先开车,小A行驶的路程长度
fb[i][j][k]: 从城市j出发,行驶2^i天,k先开车,小B行驶的路程长度
k = 0 A k = B B开车
初始化:已知小A、小B从任意城市出发会走到的城市是什么。
f[0][j][0] = ca, f[0][j][1] = cb
fa[0][j][0] = abs(h[j] - h[ca]);
fb[0][j][0] = abs(h[j] - h[cb]);
转移方程:
i = 1: f[1][j][k] = f[0][f[0][j][k]][k^1];
fa[1][j][k] = fa[0][j][k] + fa[0][f[0][j][k]][k^1];
fb[1][j][k] = fb[0][j][k] + fb[0][f[0][j][k]][k^1];
i > 1:
f[i][j][k] = f[i - 1][f[i - 1][j][k]][k];
从j往后走2^(i-1)天到的城市,再往后走2^(i - 1)天
fa[i][j][k] = fa[i - 1][j][k] + fa[i - 1][f[i - 1][j][k]][k];
fb[i][j][k] = fb[i - 1][j][k] + fb[i - 1][f[i - 1][j][k]][k];
*/
0 条评论
目前还没有评论...