当前位置: 移动技术网 > IT编程>开发语言>C/C++ > cf605D. Board Game(BFS 树状数组 set)

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

2019年01月01日  | 移动技术网IT编程  | 我要评论

舒向新,于娟活着就是王道,电机修理

题意

题目链接

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网