zoukankan      html  css  js  c++  java
  • cf605D. Board Game(BFS 树状数组 set)

    题意

    题目链接

    (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
    ", 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;
    }
    
  • 相关阅读:
    『题解』POJ1753 Flip Game
    『数论』乘法逆元
    『数据结构』RMQ问题
    UVA 253 Cube painting 【数学】
    POJ 1852 Ants 【水+Trick+贪心】
    POJ 2955 Brackets 【区间DP】
    LOJ 1422 Halloween Costumes【区间DP】
    HDU 4193 Non-negative Partial Sums 【单调队列】
    CodeForces-545C Woodcutters 【贪心+机智】
    CodeForces 19D A and B and Interesting Substrings 【前缀和】
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/10197001.html
Copyright © 2011-2022 走看看