• [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
    ",ans);
        scanf("%lld",&T);
        while (T--)
        {
            scanf("%lld%lld",&si,&xi);
            tmp = ask(si,xi);
            printf("%lld %lld
    ",tmp.first,tmp.second);
        }
        
        return 0;
    }
  • 相关阅读:
    bzoj3771 Triple
    【BZOJ-1597】土地购买 DP + 斜率优化
    【BZOJ-1911】特别行动队 DP + 斜率优化
    【BZOJ-3144】切糕 最小割-最大流
    【BZOJ-2095】Bridge 最大流 + 混合图欧拉回路 + 二分
    【BZOJ-3996】线性代数 最小割-最大流
    【BZOJ-1497】最大获利 最大流
    【BZOJ-1500】维修数列 Splay
    【BZOJ-1458】士兵占领 最大流
    【BZOJ-3626】LCA 树链剖分
  • 原文地址:https://www.cnblogs.com/evenbao/p/9336180.html
Copyright © 2020-2023  润新知