#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 条评论

目前还没有评论...