NOIP 2012 P1081 driving trip

Keywords: PHP

multiplication

The most difficult part of this problem is preprocessing.

First, set is used to preprocess the maximum and the next maximum of the absolute value of the altitude difference of each point from the back to the front.

Because the subscript of the current city can only be larger, for point i, find the subscript that is closest to its value in the set.

Then the left and right subscripts are processed in set, and the maximum value and the next minimum value are taken.

Pretreatment completed

Think of every small A and B drive as A wheel drive

Then, g[i][j] is used to indicate the point from the ith point after the 2^j wheel drive.

la[i][j] refers to the distance from point I to small A driven by wheel 2^j.

lb[i][j] refers to the distance from point I to small B driven by wheel 2^j.

And then there's multiplication.

It should also be noted that when the complete round can not be carried out, small A may drive another round of car, just judge.

#include <bits/stdc++.h>
#define ll long long
#define inf 1e9
using namespace std;
const ll MAXN=100100;
ll n,x0,a[MAXN],b[MAXN],g[MAXN][32];
ll h[MAXN],where,ding,m;
ll la[MAXN][32],lb[MAXN][32];
double MIN;
set <pair<ll,ll> > s;
bool cmp(pair<ll,ll> a,pair<ll,ll> b)
{
    return (abs(a.first-ding)<abs(b.first-ding) || (abs(a.first-ding)==abs(b.first-ding) && h[a.second]<h[b.second]));
}
int main()
{
    scanf("%lld",&n);
    for (ll i=1;i<=n;i++)
      scanf("%lld",&h[i]);
    a[n]=b[n]=-1;//-1 means no more driving
    s.insert(make_pair(h[n],n));
    b[n-1]=n;a[n-1]=-1;
    s.insert(make_pair(h[n-1],n-1));
    for (ll i=n-2;i>=1;i--)//Preprocessing
    {
        bool bl=0;
        set <pair<ll,ll> > :: iterator it,be;
        vector <pair<ll,ll> > k;
        k.clear();
        it=s.lower_bound(make_pair(h[i],i));
        be=s.begin();
        be--;
        if (it!=s.end())
        {
            k.push_back(*it);
            it++;
            bl=1;
        }
        if (it!=s.end())
          k.push_back(*it);
        if (bl)
          it--;
        it--;
        if (it!=be)
        {
            k.push_back(*it);
            it--;
        }
        if (it!=be)
          k.push_back(*it);//Handle the left and right 4 points
        ding=h[i];
        sort(k.begin(),k.end(),cmp);
        b[i]=k[0].second;//Take the maximum
        a[i]=k[1].second;//Take second big
        s.insert(make_pair(h[i],i));
    }
    for (ll i=1;i<=n;i++)
    {
        g[i][0]=-1;
        if (a[i]!=-1 && b[a[i]]!=-1)
        {
            la[i][0]=abs(h[i]-h[a[i]]);
            lb[i][0]=abs(h[a[i]]-h[b[a[i]]]);
            g[i][0]=b[a[i]];//Multiplication pretreatment
        }
    }
    for (ll i=1;i<=30;i++)
    {
        for (ll j=1;j<=n;j++)
        {
            if (g[j][i-1]!=-1 && g[g[j][i-1]][i-1]!=-1)//Guarantee not to exceed the scope
            {
                g[j][i]=g[g[j][i-1]][i-1];
                la[j][i]=la[j][i-1]+la[g[j][i-1]][i-1];
                lb[j][i]=lb[j][i-1]+lb[g[j][i-1]][i-1];//Doubling
            }
            else
              g[j][i]=-1;
        }
    }
    scanf("%lld",&x0);
    MIN=1.0e18+10;
    where=0;
    for (ll i=1;i<=n;i++)
    {
        ll ta,tb,now;
        ta=tb=0;
        now=i;
        for (ll j=30;j>=0;j--)//search
        {
            if (g[now][j]!=-1 && ta+tb+la[now][j]+lb[now][j]<=x0)
            {
                ta+=la[now][j];
                tb+=lb[now][j];
                now=g[now][j];
            }
        }
        if (a[now]!=-1 && ta+tb+abs(h[now]-h[a[now]])<=x0)
        {
            ta+=abs(h[now]-h[a[now]]);
            now=a[now];
        }
        double temp;
        if (tb==0)
          temp=1.0e18;
        else
          temp=(double)(1.0*ta)/(1.0*tb);
        if (temp<MIN)
        {
            MIN=temp;
            where=i;
        }
        else
        if (temp==MIN)
        {
            if (h[i]>h[where])
              where=i;
        }
    }
    printf("%lld\n",where);
    scanf("%lld",&m);
    for (ll i=1;i<=m;i++)
    {
        ll now,x;
        scanf("%lld%lld",&now,&x);
        ll ta,tb;
        ta=tb=0;
        for (ll j=30;j>=0;j--)
        {
            if (g[now][j]!=-1 && ta+tb+la[now][j]+lb[now][j]<=x)
            {
                ta+=la[now][j];
                tb+=lb[now][j];
                now=g[now][j];
            }
        }
        if (a[now]!=-1 && ta+tb+abs(h[now]-h[a[now]])<=x)
        {
            ta+=abs(h[now]-h[a[now]]);
            now=a[now];
        }
        printf("%lld %lld\n",ta,tb);
    }
}

Posted by sandrine2411 on Tue, 22 Oct 2019 10:43:56 -0700