cf605D. Board Game(BFS 树状数组 set)
程序员文章站
2022-07-27 11:26:19
题意 "题目链接" 有$n$张牌,每张牌有四个属性$(a, b, c, d)$,主人公有两个属性$(x, y)$(初始时为(0, 0)) 一张牌能够被使用当且仅当$a define Pair pair define MP(x, y) make_pair(x, y) define fi first d ......
题意
有\(n\)张牌,每张牌有四个属性\((a, b, c, d)\),主人公有两个属性\((x, y)\)(初始时为(0, 0))
一张牌能够被使用当且仅当\(a < x, b < y\),使用后\(x\)会变为\(c\),\(y\)会变为\(d\)
问使用第\(n\)张牌的最小步数
sol
直接从\((0, 0)\)开始大力bfs,那么第一次到达时就是最小的,同时记录一下前驱
现在的问题就是如何知道哪些点可以选,也就是找到所有\(a < x, b < y\)的点,可以直接树状数组+set维护
由于保证了每个元素只出现一次,因此总复杂度为\(o(nlog^2n)\)
#include<bits/stdc++.h> #define pair pair<int, int> #define mp(x, y) make_pair(x, y) #define fi first #define se second #define pb(x) push_back(x) // #define int long long #define ll long long #define pt(x) printf("%d ", x); #define fin(x) {freopen(#x".in","r",stdin);} #define fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int maxn = 2e5 + 10, inf = 1e9 + 10, mod = 1e9 + 7; const double eps = 1e-9; void chmax(int &a, int b) {a = (a > b ? a : b);} void chmin(int &a, int b) {a = (a < b ? a : b);} int sqr(int x) {return x * x;} int add(int x, int y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} void add2(int &x, int y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} int mul(int x, int y) {return 1ll * x * y % mod;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int n, a[maxn], b[maxn], c[maxn], d[maxn], vis[maxn], dis[maxn], pre[maxn], da[maxn], num; #define lb(x) (x & (-x)) #define sit set<pair>::iterator set<pair> t[maxn]; void add(int x, int v, int id) { for(; x <= num; x += lb(x)) t[x].insert(mp(v, id)); } vector<int> query(int p) { int x = a[p], y = b[p]; vector<int> res; for(; x; x -= lb(x)) { set<pair> &now = t[x]; while(1) { sit it = now.lower_bound(mp(y, 0)); if(it == now.end()) break; res.pb(it -> se); now.erase(it); } } return res; } void des() { sort(da + 1, da + num + 1); num = unique(da + 1, da + num + 1) - da - 1; for(int i = 1; i <= n; i++) { a[i] = num - (lower_bound(da + 1, da + num + 1, a[i]) - da) + 1; c[i] = num - (lower_bound(da + 1, da + num + 1, c[i]) - da) + 1; if(i != n) add(c[i], d[i], i); } } void print(int t) { printf("%d\n", dis[t]); for(int u = t; ~u; u = pre[u]) printf("%d ", u); } void bfs() { queue<int> q; q.push(n); pre[n] = -1; dis[n] = 1; while(!q.empty()) { int p = q.front(); q.pop(); if(a[p] == num && !b[p]) {print(p); return ;} vector<int> nxt = query(p); for(int i = 0, t; i < nxt.size(); i++) { if(vis[nxt[i]]) continue; vis[nxt[i]] = 1; q.push(t = nxt[i]); dis[t] = dis[p] + 1, pre[t] = p; } } puts("-1"); } signed main() { n = read(); bool flag = 0; for(int i = 1; i <= n; i++) { a[i] = read(), b[i] = read(), c[i] = read(), d[i] = read(); da[++num] = a[i]; da[++num] = c[i]; flag |= (!a[i] && !b[i]); } if(!flag) return puts("-1"); des(); bfs(); return 0; }