[NOIP 2012] 开车旅行

[题目链接]

        https://www.luogu.org/problemnew/show/P1081

[算法]

         STL-set + 倍增 + DP

[代码]

       

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define MAXLOG 20
typedef long long ll;

struct info
{
    ll height;
    ll id;
    friend bool operator < (info a,info b)
    {
        return a.height < b.height;
    }
} a[MAXN];

ll i,j,n,T,ans,x0,si,xi;
set< info > s;
ll ga[MAXN],gb[MAXN];
ll x,y;
ll f[MAXN][MAXLOG],da[MAXN][MAXLOG],db[MAXN][MAXLOG];
pair<ll,ll> tmp;

inline bool cmp(info x,info y)
{
    if (x.height != y.height) return x.height < y.height;
    else return a[x.id].height < a[y.id].height;
}
inline void get(ll id)
{
    ll len = 0;
    set< info > :: iterator it;
    info tmp[10];
    it = s.find(a[id]);
    if (it != s.begin())
    {
        it--;
        tmp[++len] = (info){a[id].height - it -> height,it -> id};
        if (it != s.begin())
        {
            it--;
            tmp[++len] = (info){a[id].height - it -> height,it -> id};    
            it++;
        }    
        it++;
    }
    it++;
    if (it != s.end()) 
    {
        tmp[++len] = (info){it -> height - a[id].height,it -> id};
        it++;
        if (it != s.end()) tmp[++len] = (info){it -> height - a[id].height,it -> id};
    }
    sort(tmp+1,tmp+len+1,cmp);
    ga[id] = tmp[1].id;
    if (len == 1) return;
    gb[id] = tmp[2].id;
}
inline pair<ll,ll> ask(ll pos,ll d)
{
    ll i;
    ll ans1 = 0,ans2 = 0;
    for (i = MAXLOG - 1; i >= 0; i--)
    {
        if (f[pos][i] && ans1 + ans2 + da[pos][i] + db[pos][i] <= d)
        {
            ans1 += da[pos][i];
            ans2 += db[pos][i];
            pos = f[pos][i];
        }
    }
    if (gb[pos])
    {
        if (ans1 + ans2 + abs(a[pos].height - a[gb[pos]].height) <= d)
            ans1 += abs(a[pos].height - a[gb[pos]].height);
    }
    return make_pair(ans1,ans2);
}
int main()
{
    
    scanf("%lld",&n);
    for (i = 1; i <= n; i++) 
    {
        scanf("%lld",&a[i].height);
        a[i].id = i;
    }
    for (i = n; i >= 1; i--)
    {
        s.insert(a[i]);
        if (i != n) get(i);    
    }
    for (i = 1; i <= n; i++)
    {
        f[i][0] = ga[gb[i]];
        if (gb[i]) da[i][0] = abs(a[i].height - a[gb[i]].height);
        if (gb[i] && ga[gb[i]]) db[i][0] = abs(a[gb[i]].height - a[ga[gb[i]]].height);     
    }
    for (j = 1; j < MAXLOG; j++)
    {
        for (i = 1; i <= n; i++)
        {
            f[i][j] = f[f[i][j-1]][j-1];
            da[i][j] = da[i][j-1] + da[f[i][j-1]][j-1];
            db[i][j] = db[i][j-1] + db[f[i][j-1]][j-1];
        }
    }
    scanf("%lld",&x0);
    ans = 0;
    x = y = 0;
    for (i = 1; i <= n; i++)
    {
        tmp = ask(i,x0);
        if (tmp.second != 0 && (!ans || tmp.first * y < tmp.second * x))
        {
            ans = i;
            x = tmp.first;
            y = tmp.second;
        }
    }
    printf("%lld\n",ans);
    scanf("%lld",&T);
    while (T--)
    {
        scanf("%lld%lld",&si,&xi);
        tmp = ask(si,xi);
        printf("%lld %lld\n",tmp.first,tmp.second);
    }
    
    return 0;
}

 

posted @ 2018-07-19 15:40  evenbao  阅读(189)  评论(0编辑  收藏  举报