zoukankan      html  css  js  c++  java
  • Problem 1 bfs+set

    $des$

    小G有一个长度为 $n$ 的 01 串 T ,其中只有 $T_S = 1$,其余位置都是 $0$。现在小G可以进行若干
    次以下操作:
    选择一个长度为 $K$ 的连续子串(K是给定的常数),翻转这个子串。
    对于每个 $i,i ∈ [1,n]$,小G想知道最少要进行多少次操作使得 $T_i = 1$. 特别的,有 $m$ 个 “禁
    止位置”,你需要保证在操作过程中 $1$ 始终不在任何一个禁止位置上。

    $sol$

    考虑当前在每个点时可以通过一次翻转转移到哪些点,直接遂遆道即可算出每个点的所需步
    数。然而边数会达到 $O(n ^ 2)$ 级别。
    可以发现转移到的点一定是一段区间内的奇数或者偶数点,于是一种简单的优化
    方法是在 BFS 时开两个 SET 维护当前有哪些奇数点和偶数点还未被 BFS 到,转移时直接
    在 SET 上 lower_bound,就不会访问已经 BFS 到过的点了。$O(nlogn)$  

    $code$

    #include <bits/stdc++.h>
    
    #define Rep(i, j, k) for (int i = j; i <= k; i++)
    
    using namespace std;
    
    const int N = 1e5 + 10;
    
    int n, K, m, S;
    int dis[N];
    bool ban[N];
    set<int> add1, even2;
    
    void BFS() {
        memset(dis, -1, sizeof dis);
        queue<int> q;
        dis[S] = 0, q.push(S);
        while (!q.empty()) {
            int o = q.front(); q.pop();
            int L = max(1, o - K + 1), R = min(n, o + K - 1);
            L = L + (L + K - 1) - o, R = R + (R - K + 1) - o;
    //        cout << o << " " << L << " " << R << "
    "; 
            set<int> &p = L & 1 ? add1 : even2;
            for (set<int> :: iterator i = p.lower_bound(L); i != p.end() && *i <= R; p.erase(i++))
                dis[*i] = dis[o] + 1, q.push(*i);
        }
    }
    
    int main() {
        scanf("%d%d%d%d", &n, &K, &m, &S);
        Rep(i, 1, m) {
            int x;
            scanf("%d", &x);
            ban[x] = true;
        }
        Rep(i, 1, n) if (!ban[i] && i != S) i & 1 ? add1.insert(i) : even2.insert(i);
        BFS();
        Rep(i, 1, n) printf("%d ", dis[i]);
        return 0;
    }
  • 相关阅读:
    redis 内存管理与数据淘汰机制(转载)
    Memcached特性及优缺点
    二叉树深度优先遍历和广度优先遍历
    电商 秒杀系统 设计思路和实现方法(转载)
    6种负载均衡算法
    解决like '%字符串%'时索引不被使用的方法
    哪些情况下索引会失效?
    PreferenceActivity详解
    sun.misc.BASE64Encoder在Eclipse中不能直接使用的原因和解决方案
    单点登录原理与简单实现
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9767164.html
Copyright © 2011-2022 走看看