zoukankan      html  css  js  c++  java
  • 2020-08-09 提高组模拟赛选讲

    Problem T1. 雷神领域

    生成新的点的性质是两个坐标都已经配对过,也就是在同一个连通块中。

    考虑并查集维护,每次将。

    时间复杂度 (mathcal O(n^2))

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int _max = 5000;
    
    int fa[10005];
    int dp[5005][5005];
    int n; 
    
    int get(int x) {
      return fa[x] == x ? x : fa[x] = get(fa[x]); 
    }
    
    int main() {
      ios::sync_with_stdio(false);
      cin.tie(0);
      cout.tie(0); 
      cin >> n;
      for (int i = 1; i <= 10000; ++i) 
        fa[i] = i; 
      for (int i = 1, x, y; i <= n; ++i) {
        cin >> x >> y;
        int p = get(x), q = get(y + _max);
        if (p != q) {
          fa[p] = q;
        }
      }
      dp[0][0] = 0; 
      for (int i = 1; i <= _max; ++i) 
        for (int j = 1; j <= _max; ++j) 
          if (get(i) == get(j + _max)) {
            dp[i][j] = dp[i - 1][j - 1] + 1; 
          } else {
            dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); 
          }
      cout << dp[_max][_max] << '
    ';
      return 0; 
    }
    

    Problem T2. 密码锁

    和启智树暑假集训的一道题相似,考虑对于原序列每一个元素和前一个元素异或一下,维护操作后的序列。

    对于每两个相邻的 (1) 之间的点必须要进行奇数次操作。

    因为需要精准覆盖,可以看做一个图,用广搜预处理出从一个点开始,把一堆连续的点变成合法的最小步数。

    然后只剩下 (2k) 个点,可以状压 DP。

    (dp[mask]) 表示当前已经处理好的状态为 (mask) 的最小步数。

    每次要覆盖两个节点,所以 (dp[mask]=Min{dp[last]+move[i][j]})

    时间复杂度 (mathcal O(2k imes m+2^{20}2k))

    #include <bits/stdc++.h>
    
    using namespace std;
    
    template <typename T>
    void read(T& x) {
      x = 0; 
      int c = 0, f = 0;
      for (; !isdigit(c); c = getchar()) f |= c == '-';
      for (; isdigit(c); c = getchar()) x = x * 10 + (c & 15);
      x = f ? -x : x; 
    }
    
    const int N = 1e4 + 5, M = 2e6 + 5;
    
    int a[N], x[N], num[N], dis[N], s[N], d[25][25];
    int dp[M], vis[M];
    int n, m, k, cnt;
    
    void spfa(int x) {
      queue<int> q;
      memset(vis, 0, sizeof vis);
      q.push(x); 
      vis[x] = 1;
      dis[x] = 0;
      while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = 1; i <= m; ++i) {
          if (u + s[i] <= n && !vis[u + s[i]]) {
            vis[u + s[i]] = 1; 
            dis[u + s[i]] = dis[u] + 1;
            q.push(u + s[i]); 
          }
          if (u - s[i] > 0 && !vis[u - s[i]]) {
            vis[u - s[i]] = 1;
            dis[u - s[i]] = dis[u] + 1;
            q.push(u - s[i]); 
          }
        }
      }
      for (int i = 1; i <= n; ++i) 
        if (num[i]) 
          if (!vis[i]) 
            d[num[x]][num[i]] = 0x3f3f3f3f;
          else 
            d[num[x]][num[i]] = dis[i];
    }
    
    int dfs(int mask) {
      if (!mask) 
        return 0;
      if (vis[mask]) 
        return dp[mask];
      vis[mask] = 1, dp[mask] = 0x3f3f3f3f;
      int s = 0;
      for (int i = 1; i <= cnt; ++i) {
        if (mask >> (i - 1) & 1) {
          if (!s) 
            s = i;
          else {
            if (d[s][i] != 0x3f3f3f3f) 
              dp[mask] = min(dp[mask], dfs(mask ^ (1 << (s - 1)) ^ (1 << (i - 1))) + d[s][i]); 
          }
        }
      }
      return dp[mask];
    }
    
    int main() {
      freopen("password.in", "r", stdin);
      freopen("password.out", "w", stdout); 
      read(n), read(k), read(m);
      for (int i = 1; i <= k; ++i) {
        read(x[i]);
        a[x[i]] = 1;
      }
      for (int i = 1; i <= m; ++i)
        read(s[i]); 
      ++n; 
      for (int i = n; i >= 1; --i) 
        a[i] ^= a[i - 1];
      for (int i = 1; i <= n; ++i) 
        if (a[i])
          num[i] = ++cnt;
      for (int i = 1; i <= n; ++i) 
        if (a[i]) 
          spfa(i);
      memset(vis, 0, sizeof vis); 
      dfs((1 << cnt) - 1); 
      if (dp[(1 << cnt) - 1] == 0x3f3f3f3f) 
        printf("-1
    ");
      else 
        printf("%d
    ", dp[(1 << cnt) - 1]); 
      return 0; 
    }
    

    Problem T3. 花园

    考虑维护从根节点开始到某一个节点的某个颜色的答案,这样就可以变成子树修改,单点查询。

    时间复杂度 (mathcal O(n+qlog n))

    #include <bits/stdc++.h>
    
    using namespace std;
    
    template <typename T>
    void read(T& x) {
      x = 0; 
      int c = 0, f = 0;
      for (; !isdigit(c); c = getchar()) f |= c == '-';
      for (; isdigit(c); c = getchar()) x = x * 10 + (c & 15);
      x = f ? -x : x; 
    }
    
    const int N = 1e5 + 5;
    
    struct edge {
      int v, nxt;
    } e[N << 1];
    
    int head[N];
    int edge_cnt;
    
    void add_edge(int u, int v) {
      e[++edge_cnt] = (edge){v, head[u]};
      head[u] = edge_cnt;
    }
    
    int n, q;
    int fa[N], sz[N], top[N], son[N], dep[N], dfn[N];
    int dfc, color_cnt = 1; 
    map<int, int> disc;
    int root[N * 3], col[N];
    
    void Dfs(int u, int father) {
      son[u] = 0;
      dep[u] = dep[father] + 1;
      fa[u] = father;
      sz[u] = 1;
      for (int i = head[u]; i; i = e[i].nxt) {
        if (e[i].v != father) {
          Dfs(e[i].v, u);
          sz[u] += sz[e[i].v];
          if (sz[e[i].v] > sz[son[u]]) 
            son[u] = e[i].v;
        }
      }
    }
    
    void dfs(int u, int tp) {
      top[u] = tp, dfn[u] = ++dfc;
      if (!son[u]) 
        return; 
      dfs(son[u], tp);
      for (int i = head[u]; i; i = e[i].nxt) 
        if (e[i].v != fa[u] && e[i].v != son[u]) 
          dfs(e[i].v, e[i].v);
    }
    
    int lca(int u, int v) {
      while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) 
          swap(u, v);
        u = fa[top[u]];
      }
      return dep[u] < dep[v] ? u : v; 
    }
    
    struct node {
      int ch[2];
      int val;
      int tag;
    } seg[N * 100];
    
    int node_cnt = 0;
    
    void pushdown(int p, int l, int r) {
      if (seg[p].tag == 0 || l == r) 
        return;
      if (seg[p].ch[0] == 0) 
        seg[p].ch[0] = ++node_cnt;
      if (seg[p].ch[1] == 0)
        seg[p].ch[1] = ++node_cnt;
      seg[seg[p].ch[0]].tag += seg[p].tag; 
      seg[seg[p].ch[1]].tag += seg[p].tag;
      seg[seg[p].ch[0]].val += seg[p].tag;
      seg[seg[p].ch[1]].val += seg[p].tag;
      seg[p].tag = 0; 
    }
    
    void modify(int& p, int l, int r, int ql, int qr, int v) {
      if (!p) 
        p = ++node_cnt;
      if (ql <= l && r <= qr) {
        seg[p].tag += v;
        seg[p].val += v;
        return;
      }
      pushdown(p, l, r);
      int mid = l + r >> 1;
      if (ql <= mid) 
        modify(seg[p].ch[0], l, mid, ql, qr, v);
      if (qr > mid)
        modify(seg[p].ch[1], mid + 1, r, ql, qr, v);
    }
    
    int query(int p, int l, int r, int pos) {
      if (!p) 
        return 0;
      if (l == r) 
        return seg[p].val;
      pushdown(p, l, r);
      int mid = l + r >> 1;
      if (pos <= mid)
        return query(seg[p].ch[0], l, mid, pos);
      else 
        return query(seg[p].ch[1], mid + 1, r, pos); 
    }
    
    int main() {
      read(n), read(q); 
      for (int i = 1; i <= n; ++i) {
        int t;
        read(t); 
        if (!disc.count(t)) 
          disc[t] = ++color_cnt;
        col[i] = disc[t];
      }
      for (int i = 1; i < n; ++i) {
        int u, v;
        read(u), read(v); 
        add_edge(u, v);
        add_edge(v, u);
      }
      Dfs(1, 0); 
      dfs(1, 1); 
      for (int i = 1; i <= n; ++i) 
        modify(root[col[i]], 1, n, dfn[i], dfn[i] + sz[i] - 1, 1); 
      char opt[5];
      int x, y, t;
      for (int qt = 1, last_ans = 0; qt <= q; ++qt) {
        scanf("%s", opt);
        if (opt[0] == 'C') {
          read(x), read(t); 
          x ^= last_ans, t ^= last_ans;
          if (!disc.count(t)) 
            disc[t] = ++color_cnt;
          t = disc[t];
          modify(root[col[x]], 1, n, dfn[x], dfn[x] + sz[x] - 1, -1);
          modify(root[t], 1, n, dfn[x], dfn[x] + sz[x] - 1, 1);
          col[x] = t; 
        } else {
          read(x), read(y), read(t); 
          x ^= last_ans, y ^= last_ans, t ^= last_ans;
          if (!disc.count(t)) 
            disc[t] = ++color_cnt;
          t = disc[t];
          int _lca = lca(x, y), ans;
          ans = query(root[t], 1, n, dfn[x]) + query(root[t], 1, n, dfn[y]);
          ans -= 2 * query(root[t], 1, n, dfn[_lca]);
          if (col[_lca] == t)
            ++ans;
          printf("%d
    ", last_ans = ans);  
        }
      }
      return 0; 
    }
    
  • 相关阅读:
    xtrabackup备份原理
    四“当”
    MySQL BinLog Server 搭建实战
    mysqldump 原理
    MGR测试及搭建
    自动化测试-12.selenium的弹出框处理
    自动化测试-11.selenium的下拉框处理类Select
    自动化测试-10.selenium的iframe与Frame
    自动化测试-9.selenium多窗口句柄的切换
    自动化测试-8.selenium操作元素之键盘和鼠标事件
  • 原文地址:https://www.cnblogs.com/chhokmah/p/13528825.html
Copyright © 2011-2022 走看看