• Goodbye Yiwei


    A

    贪心的取,后缀 (min) 比栈顶和栈底小就一直取到后缀 (min),否则取栈顶和栈底中最小的。

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-8, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((int)(x).size())
    
    const int MAXN = 100000 + 5;
    
    std::deque<int> dq;
    int a[MAXN], suf[MAXN];
    
    int main() {
      int T;
      scanf("%d", &T);
      while (T --) {
        dq.clear();
        int n;
        scanf("%d", &n);
        For(i, 1, n) {
          scanf("%d", &a[i]);
        }
        suf[n + 1] = INF;
        Rep(i, n, 1) {
          suf[i] = mymin(suf[i + 1], a[i]);
        }
        int cur = 1, cnt = 0;
        while (cnt < n) {
          while (dq.empty() || mymin(dq.front(), dq.back()) > suf[cur]) {
            dq.push_back(a[cur ++]);
          }
          while (!dq.empty() && mymin(dq.front(), dq.back()) < suf[cur]) {
            if (dq.front() < dq.back()) {
              printf("%d ", dq.front());
              dq.pop_front();
            } else {
              printf("%d ", dq.back());
              dq.pop_back();
            }
            ++ cnt;
          }
        }
        puts("");
      }
      return 0;
    }
    

    B

    一个点是安全的当且仅当:

    1.它的度数为 (1)
    2.它和一个度数为 (1) 的点相连;
    3.存在一个点,忽略它和这个点的连边后这两个点相邻的点相同。

    前两个条件很好判断,第三个条件如果两个点不相邻排个序就行了,相邻的话直接枚举每条边然后暴力判断即可。

    这个暴力复杂度是对的,因为它等价于这个式子:

    [sum^m[deg_u = deg_v]deg_u ]

    每个点至多贡献 (O(sqrt{m})) 次,而所有点的度数和为 (O(m)),所以复杂度是 (O(msqrt{m}))

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-8, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((int)(x).size())
    
    struct Input {
      char buf[1 << 25], *s;
    
      Input() {
    #ifndef ONLINE_JUDGE
        freopen("police.in", "r", stdin);
    #endif
        fread(s = buf, 1, 1 << 25, stdin);
      }
    
      friend Input &operator>>(Input &io, int &x) {
        x = 0;
        while (!isdigit(*io.s)) {
          ++ io.s;
        }
        while (isdigit(*io.s)) {
          x =  x * 10 + *io.s ++ - '0';
        }
        return io;
      }
    } cin;
    
    const int MAXN = 100000 + 5, MAXM = 200000 + 5;
    
    struct Edge {
      int u, v;
    } edge[MAXM];
    
    std::vector<int> adj[MAXN];
    std::pair<std::vector<int>, int> tp[MAXN];
    int deg[MAXN];
    bool ok[MAXN];
    
    int main() {
      int T;
      cin >> T;
      while (T --) {
        int n, m;
        cin >> n >> m;
        memset(deg, 0, sizeof deg);
        memset(ok, 0, sizeof ok);
        For(i, 1, n) {
          adj[i].clear();
        }
        For(i, 1, m) {
          cin >> edge[i].u >> edge[i].v;
          ++ deg[edge[i].u], ++ deg[edge[i].v];
          adj[edge[i].u].push_back(edge[i].v);
          adj[edge[i].v].push_back(edge[i].u);
        }
        For(i, 1, n) {
          std::sort(adj[i].begin(), adj[i].end());
          tp[i] = {adj[i], i};
        }
        std::sort(tp + 1, tp + n + 1);
        FOR(i, 1, n) {
          if (tp[i].first == tp[i + 1].first) {
            ok[tp[i].second] = ok[tp[i + 1].second] = 1;
          }
        }
        For(i, 1, m) {
          if (deg[edge[i].u] == 1 || deg[edge[i].v] == 1) {
            ok[edge[i].u] = ok[edge[i].v] = 1;
          }
        }
        For(i, 1, m) {
          if ((!ok[edge[i].u] || !ok[edge[i].v]) && deg[edge[i].u] == deg[edge[i].v]) {
            int u = edge[i].u, v = edge[i].v;
            bool yes = 1;
            for (int x = 0, y = 0; x < SZ(adj[u]) && y < SZ(adj[v]); ++ x, ++ y) {
              if (adj[u][x] == v) {
                ++ x;
              }
              if (adj[v][y] == u) {
                ++ y;
              }
              if (x >= SZ(adj[u]) || y >= SZ(adj[v])) {
                break;
              }
              if (adj[u][x] != adj[v][y]) {
                yes = 0;
                break;
              }
            }
            if (yes) {
              ok[u] = ok[v] = 1;
            }
          }
        }
        int cnt = 0;
        For(i, 1, n) {
          cnt += ok[i];
        }
        printf("%d
    ", cnt);
        For(i, 1, n) {
          if (ok[i]) {
            printf("%d ", i);
          }
        }
        puts("");
      } 
      return 0;
    }
    

    C

    考虑 Boruvka 算法,每轮给每个连通块赋一个颜色,然后逐位确定最大连边的权值,可以发现你实际上要求的是某个集合的超集的最大值和次大值(为了判断是否只有一种颜色),高维前缀和即可。

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-8, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((int)(x).size())
    
    const int MAXN = 100000 + 5, MASK = 1 << 18;
    
    struct DisjointSet {
      int fa[MAXN];
    
      void init(int n) {
        For(i, 1, n) {
          fa[i] = i;
        }
      }
    
      int find(int u) {
        return fa[u] == u ? u : fa[u] = find(fa[u]);
      }
    
      bool same(int u, int v) {
        return find(u) == find(v);
      }
    
      void merge(int u, int v) {
        if (!same(u, v)) {
          fa[fa[v]] = fa[u];
        }
      }
    } dsu;
    
    int a[MAXN], col[MAXN], tp[MAXN], to[MAXN], val[MAXN], col_sec[MASK], col_max[MASK], num_sec[MASK], num_max[MASK];
    
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("andmst.in", "r", stdin);
    #endif
      int n, m;
      scanf("%d%d", &n, &m);
      For(i, 1, n) {
        scanf("%d", &a[i]);
      }
      int cnt = 0, cur = n;
      For(i, 1, n) {
        col[i] = i;
      }
      LL ans = 0;
      while (cnt < n - 1) {
        dsu.init(cur);
        memset(col_sec, 0, sizeof col_sec);
        memset(col_max, 0, sizeof col_max);
        memset(num_sec, 0, sizeof num_sec);
        memset(num_max, 0, sizeof num_max);
        For(i, 1, n) {
          if (col_max[a[i]] < col[i]) {
            col_sec[a[i]] = col_max[a[i]];
            col_max[a[i]] = col[i];
            num_sec[a[i]] = num_max[a[i]];
            num_max[a[i]] = i;
          } else if (col_max[a[i]] != col[i] && col_sec[a[i]] < col[i]) {
            col_sec[a[i]] = col[i];
            num_sec[a[i]] = i;
          }
        }
        FOR(i, 0, m) {
          REP(S, 1 << m, 0) {
            if ((~S >> i) & 1) {
              if (col_max[S] < col_max[S | (1 << i)]) {
                col_sec[S] = col_max[S];
                col_max[S] = col_max[S | (1 << i)];
                num_sec[S] = num_max[S];
                num_max[S] = num_max[S | (1 << i)];
                if (col_sec[S] < col_sec[S | (1 << i)]) {
                  col_sec[S] = col_sec[S | (1 << i)];
                  num_sec[S] = num_sec[S | (1 << i)];
                }
              } else if (col_max[S] != col_max[S | (1 << i)] && col_sec[S] < col_max[S | (1 << i)]) {
                col_sec[S] = col_max[S | (1 << i)];
                num_sec[S] = num_max[S | (1 << i)];
              } else if (col_max[S] == col_max[S | (1 << i)] && col_sec[S] < col_sec[S | (1 << i)]) {
                col_sec[S] = col_sec[S | (1 << i)];
                num_sec[S] = num_sec[S | (1 << i)];
              }
            }
          }
        }
        For(i, 1, cur) {
          to[i] = 0, val[i] = -1;
        }
        For(i, 1, n) {
          int s = 0;
          REP(j, m, 0) {
            if ((a[i] >> j) & 1) {
              int t = s << 1 | 1, p = t << j;
              if (col_max[p] && (col_max[p] != col[i] || (col_sec[p] && col_sec[p] != col[i]))) {
                s = t;
              } else {
                s = t - 1;
              }
            } else {
              s <<= 1;
            }
          }
          int v = col_max[s] == col[i] ? num_sec[s] : num_max[s], w = a[i] & a[v];
          if (chkmax(val[col[i]], w)) {
            to[col[i]] = col[v];
          }
        }
        For(i, 1, cur) {
          if (!dsu.same(i, to[i])) {
            dsu.merge(i, to[i]);
            ++ cnt;
            ans += val[i];
          }
        }
        int fn = 0;
        For(i, 1, cur) {
          if (dsu.find(i) == i) {
            tp[i] = ++ fn;
          }
        }
        For(i, 1, cur) {
          tp[i] = tp[dsu.find(i)];
        }
        For(i, 1, n) {
          col[i] = tp[col[i]];
        }
        cur = fn;
      }
      printf("%lld
    ", ans);
      return 0;
    }
    

    D

    先二分答案,然后考虑倒着做,把合并变成划分,然后就变成了你初始有一个雷,每次你可以把一个威力为 (k) 的雷变成 (m) 个威力为 ({k - b_1, k - b_2, cdots, k - b_m}) 的雷,最后要让排序后每个雷的威力都大于等于对应位置的 (a_i)

    我们称雷的集合 (S) 可以匹配集合 (T),当且仅当 (S) 可以通过一系列拆分操作使得 (|S| = |T|),且排序后 (S) 中对应位置的雷的威力都大于 (T) 中的。

    每次考虑 (S) 中最大的雷能否拆出能匹配 (T) 中最大的雷的雷,否则就把 (T) 中最大的雷匹配掉,用 multiset 维护即可。

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-8, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((int)(x).size())
    
    const int MAXN = 50000 + 5;
    
    int a[MAXN], b[MAXN];
    
    IL bool check(int n, int m, LL k) {
      std::multiset<LL> s({k}), t(a + 1, a + n + 1);
      while (SZ(s) < SZ(t)) {
        if (s.empty()) {
          return 0;
        }
        LL x = *s.rbegin(), y = *t.rbegin();
        if (x - b[1] >= y) {
          For(i, 1, m) {
            s.insert(x - b[i]);
          }
          s.erase(s.find(x));
        } else {
          auto it = s.lower_bound(y);
          if (it == s.end()) {
            return 0;
          }
          s.erase(it), t.erase(t.find(y));
        }
      }
      for (auto x = s.begin(), y = t.begin(); x != s.end() && y != t.end(); ++ x, ++ y) {
        if (*x < *y) {
          return 0;
        }
      }
      return 1;
    }
    
    int main() {
      int n, m;
      scanf("%d%d", &n, &m);
      For(i, 1, n) {
        scanf("%d", &a[i]);
      }
      For(i, 1, m) {
        scanf("%d", &b[i]);
      }
      std::sort(a + 1, a + n + 1);
      std::sort(b + 1, b + m + 1);
      LL l = a[n], r = a[n] + (LL)(n - 1) / (m - 1) * b[m], ans = 0;
      while (l <= r) {
        LL mid = (l + r) >> 1;
        if (check(n, m, mid)) {
          ans = mid, r = mid - 1;
        } else {
          l = mid + 1;
        }
      }
      printf("%lld
    ", ans);
      return 0;
    }
    

    E

    发现如果值域是 ([0,1024]) 的话可以用长为 (10240) 的串传送,于是考虑一个 hash 函数把这 (1024) 个坐标映射到这个范围上去。

    问题在于随机这个函数的话需要的次数太多了,考虑转换一下方法,每次把这些坐标分成两半,这样随机次数就可以接受了。

    但这样需要传送的次数太多了,于是可以考虑小范围用开始的方法暴力随。

    有一个问题是如果你用定长编码传送次数,那么这个定长会比较大,所以可以使用不定长编码,具体实现可以参见代码。

    #include <bits/stdc++.h>
    
    #define IL __inline__ __attribute__((always_inline))
    
    #define For(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++ i)
    #define FOR(i, a, b) for (int i = (a), i##end = (b); i < i##end; ++ i)
    #define Rep(i, a, b) for (int i = (a), i##end = (b); i >= i##end; -- i)
    #define REP(i, a, b) for (int i = (a) - 1, i##end = (b); i >= i##end; -- i)
    
    typedef long long LL;
    
    template <class T>
    IL bool chkmax(T &a, const T &b) {
      return a < b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL bool chkmin(T &a, const T &b) {
      return a > b ? ((a = b), 1) : 0;
    }
    
    template <class T>
    IL T mymax(const T &a, const T &b) {
      return a > b ? a : b;
    }
    
    template <class T>
    IL T mymin(const T &a, const T &b) {
      return a < b ? a : b;
    }
    
    template <class T>
    IL T myabs(const T &a) {
      return a > 0 ? a : -a;
    }
    
    const int INF = 0X3F3F3F3F;
    const double EPS = 1E-8, PI = acos(-1.0);
    
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define OK DEBUG("Passing [%s] in LINE %d...
    ", __FUNCTION__, __LINE__)
    #define SZ(x) ((int)(x).size())
    
    const int MAXN = 1024, MAXM = 20000 + 5;
    
    IL unsigned xorShift() {
      static unsigned x = 20030102;
      x ^= x << 13;
      x ^= x >> 17;
      x ^= x << 5;
      return x;
    }
    
    struct Hash {
      static const int MOD = 998244353;
    
      int a, b;
    
      Hash() : a(114514), b(1919810) {}
    
      void next() {
        a = xorShift() % MOD, b = xorShift() % MOD;
      }
    
      int get(unsigned x) {
        return ((LL)a * x + b) % MOD;
      }
    } h;
    
    namespace Encode {
    unsigned key[MAXN];
    int val[MAXN], to[MAXN], cur;
    bool ret[MAXM];
    
    IL void print(int x, int digit, bool mode) {
      if (mode) {
        int real = x ? std::__lg(x) + 1 : 0;
        For(i, 1, real - digit) {
          ret[cur ++] = 1;
        }
        ret[cur ++] = 0;
      }
      for (; x; x >>= 1, -- digit) {
        ret[cur ++] = x & 1;
      }
      for (; digit > 0; -- digit) {
        ret[cur ++] = 0;
      }
    }
    
    void solve(const std::vector<int> &v, int high) {
      static int tp[MAXN];
      int times = 0;
      if (SZ(v) <= 8) {
        while (1) {
          FOR(i, 0, 8) {
            tp[i] = -1;
          }
          FOR(i, 0, 8) {
            tp[h.get(key[v[i]]) % 8] = v[i];
          }
          bool ok = 1;
          FOR(i, 0, 8) {
            if (!~tp[i]) {
              ok = 0;
              break;
            }
          }
          if (ok) {
            break;
          }
          ++ times;
          h.next();
        }
        FOR(i, 0, 8) {
          to[high << 3 | i] = tp[i];
        }
        print(times, 9, 1);
        return;
      }
      int n = SZ(v);
      while (1) {
        FOR(i, 0, n) {
          tp[i] = h.get(key[v[i]]) % 2;
        }
        int cnt = 0;
        FOR(i, 0, n) {
          cnt += tp[i];
        }
        if (cnt == n / 2) {
          break;
        }
        ++ times;
        h.next();
      }
      print(times, 4, 1);
      std::vector<int> x, y;
      FOR(i, 0, n) {
        if (tp[i]) {
          y.push_back(v[i]);
        } else {
          x.push_back(v[i]);
        }
      }
      solve(x, high << 1), solve(y, high << 1 | 1);
    }
    
    IL void main() {
      FOR(i, 0, MAXN) {
        scanf("%u%d", &key[i], &val[i]);
      }
      std::vector<int> v(MAXN);
      FOR(i, 0, MAXN) {
        v[i] = i;
      }
      solve(v, 0);
      FOR(i, 0, MAXN) {
        print(val[to[i]], 10, 0);
      }
      FOR(i, 0, cur) {
        putchar('0' + ret[i]);
      }
      puts("");
    }
    }
    
    namespace Decode {
    unsigned val[MAXN];
    int to[MAXN], ans[MAXN], cur;
    int len;
    char str[MAXM];
    
    IL int read(int digit, bool mode) {
      int more = 0;
      if (mode) {
        while (str[cur ++] == '1') {
          ++ more;
        }
      }
      int ans = 0;
      FOR(i, 0, digit + more) {
        ans += (str[cur ++] - '0') << i;
      }
      return ans;
    }
    
    void solve(const std::vector<int> &v, int cur, int high) {
      if (cur <= 8) {
        int times = read(9, 1);
        For(i, 1, times) {
          h.next();
        }
        for (auto &x : v) {
          to[high << 3 | (h.get(val[x]) % 8)] = x;
        }
        return;
      }
      int times = read(4, 1);
      For(i, 1, times) {
        h.next();
      }
      std::vector<int> x, y;
      for (auto &a : v) {
        if (h.get(val[a]) % 2) {
          y.push_back(a);
        } else {
          x.push_back(a);
        }
      }
      solve(x, cur >> 1, high << 1), solve(y, cur >> 1, high << 1 | 1);
    }
    
    IL void main() {
      memset(to, -1, sizeof to);
      scanf("%s", str);
      len = strlen(str);
      int q;
      scanf("%d", &q);
      std::vector<int> v(q);
      FOR(i, 0, q) {
        scanf("%u", &val[i]);
        v[i] = i;
      }
      solve(v, MAXN, 0);
      FOR(i, 0, MAXN) {
        int x = read(10, 0);
        if (to[i] != -1) {
          ans[to[i]] = x;
        }
      }
      FOR(i, 0, q) {
        printf("%d
    ", ans[i]);
      }
    }
    }
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("decode.in", "r", stdin);
      freopen("decode.out", "w", stdout);
    #endif
      char str[10];
      scanf("%s", str);
      if (str[0] == 'e') {
        Encode::main();
      } else {
        Decode::main();
      }
      return 0;
    }
    
  • 相关阅读:
    性能测试之数据准备
    工作笔记
    Ruby on Rails 模型关联(多对多关系)
    oracle 分页查询优化
    mysql命令学习
    mysql 导入导出
    aix 管理网卡
    dataguard没成功创建数据文件
    aix删除网卡
    oracle rac 随笔
  • 原文地址:https://www.cnblogs.com/sjkmost/p/12197096.html
Copyright © 2020-2023  润新知