Codeforces Round #751 (Div. 2)D. Frog Traveler

D. Frog Traveler

题目大意:每个高度有ai,bi,爬到高度i可以选择跳0~ai米,落在高度j后会向下滑bj米,问跳到最高点的最小步数,和方案

思路:只会最捞的线段树优化建图

拆点后,每个点分为滑落点和跳落点,不拆点的话按照题意建图是错的,跳落点向滑落点连0的边,i可以跳到i~i-a[i],区间用线段树记录,最后跑下最短路的时候记录状态即可,复杂度O(nlogn)。

有dp做法甚至还有O(n)的dsu做法。。。

这个edge数组大小很迷,开小了一点wa了16发。。不太清楚怎么算的大小,,

#define _CRT_SECURE_NO_WARNINGS
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <list>
#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define scd(v) scanf("%d",&v)
#define scdd(a,b) scanf("%d %d",&a,&b)
#define endl "\n"
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define pb push_back
#define all(v) v.begin(),v.end()
#define mst(v,a) memset(v,a,sizeof(v))
#define ls p<<1
#define rs p<<1|1
#define int long long
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define pii pair<int , int >
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define AC return 0
const int N = 3e5 + 10;
const int M = 7200007;
const int mod = 1e9 + 7;
const double eps = 1e-7;
int n, m, s;
int a[N], b[N];
int pre[N*10];
int head[N*10];
struct  ty
{
    int next, t,val;
}edge[M];
int tot, tag;
int tr[N<<2], tr2[N*10],dis[N*10];
void add(int x, int y, int z) {
   // cout << x << "->" << y << " "<<z << endl;
    edge[++tot].t = y;
    edge[tot].val = z;
    edge[tot].next = head[x];
    head[x] = tot;
}
int build1(int p, int l, int r) //入树
{
    if (l == r)
    {
        return tr[p] = l;
    }
    tr[p] = ++tag;
    int mid = (l + r) >> 1;
    int lid = build1(lson);
    int rid = build1(rson);
    add(lid, tr[p],0);
    add(rid, tr[p],0);
    return tr[p];
}
int build2(int p, int l, int r)//出树
{
    if (l == r)
    {
        return tr2[p] = l;
    }
    tr2[p] = ++tag;
    int mid = (l + r) >> 1;
    int lid = build2(lson);
    int rid = build2(rson);
    add(tr2[p],lid,0);
    add(tr2[p],rid,0);
    return tr2[p];
}
void ini()
{
    tag = 2*n;
    build1(1, 0, n); build2(1, 0, n);
}
void update2( int p ,int l, int r  ,int x, int L, int R, int val)
{
    if (L <= l && r <= R)
    {
        add(x, tr2[p], val);
        return;
    }
    int mid = (l + r) >> 1;
    if (L <= mid) update2(lson, x, L, R, val);
    if (R >= mid + 1) update2(rson, x, L, R, val);
}
int vv[N*10];
void dij(int x)
{
    mst(dis, 0x3f);
    dis[x] = 0;
    priority_queue<pii, vector<pii>  ,greater<pii>> q;
    q.push({ 0,x });
    while (!q.empty())
    {
        int d = q.top().first;
        int x = q.top().second;
        q.pop();
        if (vv[x]) continue;
        vv[x] = 1;
        for (int i = head[x]; i; i = edge[i].next)
        {
            int y = edge[i].t;
            int len = edge[i].val;
            if (dis[x] + len < dis[y])
            {
                pre[y] = x;
                dis[y] = dis[x] + len;
                q.push({dis[y],y});
            }
        }
    }
}
void de()
{
    cout << " pre[] " << endl;
    _for(i, 1, 50) printf("%2lld ", i);
    cout << endl;
    _for(i, 1, 50) printf("%2lld ", pre[i]);
    cout << endl;
}
void solve()
{
    ini();
    _for(i, 1, n)
    {
        b[i] = min(n, i + b[i]);
    }
    _for(i, 1, n)
    {
         update2(1, 0, n, i+n, i - a[i] ,i, 1);
    }
    _for(i, 1, n)
    {
        add(i, b[i]+n, 0);
    }
    dij(2*n);
    if (dis[0] >= inf)
    {
        cout << -1 << endl;
    }
    else
    {
        cout << dis[0] << endl;
        int temp = 0;
        vector<int> res;
        res.push_back(0);
        while (pre[temp] != 2 * n)
        {
            if( 1<=pre[temp] && pre[temp]<= n )
            res.push_back(pre[temp]);
            temp = pre[temp];
        }
        for (int i = res.size() - 1; i >= 0; i--)
        {
            cout << res[i] << " ";
        }
        cout << endl;
    }
}
signed main()
{
     //freopen("data.txt","r",stdin);
    IOS;
    cin >> n;
    _for(i, 1, n) cin >> a[i];
    _for(i, 1, n) cin >> b[i];
    solve();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值