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();
}