题意:
从井底距离地面 处跳到地面。当距离地面 时,可以选择 的一个数且向上跳
,然后在
处休息。然而,当在距离地面
时休息,会下滑
。问最少需要跳跃的次数,及每次跳跃后(下滑之前)的位置。
思路:
bfs
注意此题和普通bfs不同的地方在于一般的bfs都可以对某个点 遍历所有它能到达的点
但这道题若如此做会t,考虑到假如我们从i跳到j,滑落到k,如果k已经被访问过了,那么就没有了访问j的意义。所以我们用vis[]数组表示k是否被访问过,用set表示所有能到达的j,这样所有点最多被访问2次(k, j)各一次,时间复杂度O(nlogn).
但是写set时re了很多次,注意不要让迭代器越界。insert一个负数,如果迭代器访问到了负数那就说明此时容器中只有这一个元素了,及时break
// Decline is inevitable,
// Romance will last forever.
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
#define fi first
#define se second
#define ll long long
#define LL long long
//#define int long long
const int maxn = 3e5 + 10;
const int maxm = 1e3 + 10;
const int INF = 0x3f3f3f3f;
const int dx[] = {0, 0, -1, 1}; //{0, 0, 1, 1, 1,-1,-1,-1}
const int dy[] = {1, -1, 0, 0}; //{1,-1, 1, 0,-1, 1, 0,-1}
const int P = 1e9 + 7;
int n;
int a[maxn];
int b[maxn];
int pre[maxn];
int ans[maxn];
bool vis[maxn];
set<int> s;
inline int readint(){
int a = 0, c = getchar(), f = 1;
for(; '0'>c||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
void writeint(int x){
if(x > 9) writeint(x/10);
putchar((x-x/10*10)^48);
}
void solve() {
n = readint();
for(int i = 1; i <= n; i++) a[i] = readint();
for(int i = 1; i <= n; i++) b[i] = readint();
for(int i = 0; i <= n; i++) pre[i] = -1;
for(int i = 0; i < n; i++) s.insert(i);
s.insert(-999999);
queue<pii > q;
q.push({n, n});
vis[n] = 1;
while(!q.empty()) {
pii x = q.front();
q.pop();
if(x.first - a[x.first] <= 0) {
pre[0] = x.second;
break;
}
for(set<int>::iterator i = --s.upper_bound(x.first); x.first-(*i) <= a[x.first]; ) {
// cout << *i;
if(vis[(*i)+b[*i]]) {
int it = (*i);
i--;
s.erase(it);
continue;
}
vis[(*i) + b[*i]] = 1;
pre[*i] = x.second;
q.push({(*i) + b[*i], (*i)});
i--;
if(*i < 0) break;
}
}
if(pre[0] == -1) {
cout << -1 <<'\n';
return;
}
/*
vector<int> ans;
int index = 0;
while(index != n) {
ans.pb(index);
index = pre[index];
}
printf("%d\n", (int)ans.size());
for(int i = (int)ans.size() - 1; i >= 0; i--)
printf("%d ", ans[i]);
printf("\n");
*/
int index = 0;
int p = 0;
while(index != n) {
ans[++p] = index;
index = pre[index];
}
printf("%d\n", p);
for(int i = p; i >= 1; i--)
printf("%d ", ans[i]);
printf("\n");
}
int main() {
solve();
return 0;
}