欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

cf605D. Board Game(BFS 树状数组 set)

程序员文章站 2022-04-05 10:09:29
题意 "题目链接" 有$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;
}