CTSC 2018 简要题解

Day 1

faceless

f(i,j) f ( i , j ) 表示第 i i 个人当前血量为 j 的概率,那么每次锁定操作就是做一次背包。

对于结界操作,我们需要对每个人 i i 处理出其他人有 j 个存活的概率,注意到这个dp是可逆的,所以求出总的之后暴力进行多项式除法即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 205;
const int mod = 998244353;

int n, m, q, a[N], b[N], t[N], inv[N], f[N][N], g[N][N];

inline int Qow(int x, int y) {
  int r = 1;
  for (; y; y >>= 1, x = 1LL * x * x % mod) {
    if (y & 1) {
      r = 1LL * r * x % mod;
    }
  }
  return r;
}

inline void Modify(int p, int v) {
  f[p][0] = (1LL * f[p][1] * v + f[p][0]) % mod;
  for (int i = 1; i <= a[p]; ++i) {
    f[p][i] = (1LL * f[p][i + 1] * v + 1LL * f[p][i] * (mod + 1 - v)) % mod;
  }
}

inline void Query() {
  Read(q), g[0][0] = 1;
  for (int i = 1; i <= q; ++i) {
    Read(b[i]);
    g[i][0] = 1LL * g[i - 1][0] * f[b[i]][0] % mod;
    for (int j = 1; j <= i; ++j) {
      g[i][j] = (1LL * g[i - 1][j] * f[b[i]][0] + 1LL * g[i - 1][j - 1] * (mod + 1 - f[b[i]][0])) % mod;
    }
  }
  for (int i = 1; i <= q; ++i) {
    int ans = 0;
    if (f[i][0] != 1) {
      for (int j = 0; j <= q; ++j) {
        t[j] = g[q][j];
      }
      int v = Qow(mod + 1 - f[b[i]][0], mod - 2);
      for (int j = q; j; --j) {
        int pro = 1LL * t[j] * v % mod;
        ans = (1LL * pro * (mod + 1 - f[b[i]][0]) % mod * inv[j] + ans) % mod;
        t[j - 1] = (t[j - 1] - 1LL * pro * f[b[i]][0] % mod + mod) % mod;
      }
    }
    printf("%d%c", ans, i == q ? '\n' : ' ');
  }
}

int main() {
#ifdef wxh010910
  freopen("d.in", "r", stdin);
#endif
  Read(n);
  for (int i = 1; i <= n; ++i) {
    inv[i] = Qow(i, mod - 2);
    Read(a[i]), f[i][a[i]] = 1;
  }
  Read(m);
  for (int i = 1, o; i <= m; ++i) {
    Read(o);
    if (!o) {
      int x, p, q;
      Read(x), Read(p), Read(q);
      Modify(x, 1LL * p * Qow(q, mod - 2) % mod);
    } else {
      Query();
    }
  }
  for (int i = 1; i <= n; ++i) {
    int r = 0;
    for (int j = 1; j <= a[i]; ++j) {
      r = (1LL * f[i][j] * j + r) % mod;
    }
    printf("%d%c", r, i == n ? '\n' : ' ');
  }
#ifdef wxh010910
  Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  return 0;
}

wronganswer

dep(x)+dep(y)dep(lca(x,y))dep(lca(x,y))=dis(x,y)+dis(x,y)+dep(x)dep(x)+dep(y)dep(y)2 d e p ( x ) + d e p ( y ) − d e p ( l c a ( x , y ) ) − d e p ′ ( l c a ′ ( x , y ) ) = d i s ( x , y ) + d i s ′ ( x , y ) + d e p ( x ) − d e p ′ ( x ) + d e p ( y ) − d e p ′ ( y ) 2

对第二棵树点分,在第一棵树上建立虚树跑一下树DP就行了。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 366670;
const int M = 20;
const LL inf = 1LL << 60;

int n, m, top, bel[N], siz[N], sta[N], seq[N << 1];
vector <int> adj[N];
LL ans, len[N];
bool vis[N];

struct Info {
  int c;
  LL w;

  Info(int c = 0, LL w = -inf):c(c), w(w) {}

  bool operator < (const Info &b) const {
    return w > b.w;
  }
} val[N][2];

struct Tree {
  struct Edge {
    int p, v;
    LL w;

    Edge(int p = 0, int v = 0, LL w = 0):p(p), v(v), w(w) {}
  } e[N << 1];

  int cnt, tim, l[N], p[N], q[N], dep[N], hed[N], par[N], f[M][N];
  LL dis[N];

  inline void AddEdge(int x, int y, LL w) {
    e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
    e[++cnt] = Edge(x, hed[y], w), hed[y] = cnt;
  }

  inline int Min(int x, int y) {
    return dep[x] < dep[y] ? x : y;
  }

  inline void DFS(int x) {
    p[x] = ++tim, f[0][tim] = x;
    for (int i = hed[x]; i; i = e[i].v) {
      int y = e[i].p;
      if (y != par[x]) {
        par[y] = x, dep[y] = dep[x] + 1, dis[y] = dis[x] + e[i].w, DFS(y);
      }
    }
    q[x] = tim;
  }

  inline int LCA(int x, int y) {
    if (p[x] > p[y]) {
      swap(x, y);
    }
    if (q[x] >= q[y]) {
      return x;
    }
    int k = l[p[y] - p[x] + 1];
    return par[Min(f[k][p[x]], f[k][p[y] - (1 << k) + 1])];
  }

  inline void Build() {
    DFS(1);
    for (int i = 1; i < M; ++i) {
      for (int j = 1; j + (1 << i) - 1 <= n; ++j) {
        f[i][j] = Min(f[i - 1][j], f[i - 1][j + (1 << i - 1)]);
      }
    }
    for (int i = 2; i <= n; ++i) {
      l[i] = l[i >> 1] + 1;
    }
  }

  inline void FindRoot(int x, int p, int s, int &c) {
    bool f = true;
    siz[x] = 1;
    for (int i = hed[x]; i; i = e[i].v) {
      int y = e[i].p;
      if (!vis[y] && y != p) {
        FindRoot(y, x, s, c), siz[x] += siz[y], f &= siz[y] <= s >> 1;
      }
    }
    f &= siz[x] >= s >> 1;
    if (f) {
      c = x;
    }
  }

  inline void DFS(int x, int p, int b, LL d) {
    siz[x] = 1, seq[++m] = x, bel[x] = b, len[x] = d;
    for (int i = hed[x]; i; i = e[i].v) {
      int y = e[i].p;
      if (!vis[y] && y != p) {
        DFS(y, x, b, d + e[i].w), siz[x] += siz[y];
      }
    }
  }

  inline void DP(int x) {
    val[x][0] = val[x][1] = Info();
    if (bel[x]) {
      val[x][0] = Info(bel[x], len[x] + dis[x]);
    }
    for (auto y : adj[x]) {
      DP(y);
      for (int i = 0; i < 2; ++i) {
        if (val[x][i].c) {
          for (int j = 0; j < 2; ++j) {
            if (val[y][j].c && val[y][j].c != val[x][i].c) {
              CheckMax(ans, val[x][i].w + val[y][j].w - (dis[x] << 1));
            }
          }
        }
      }
      Info tmp[4];
      tmp[0] = val[x][0], tmp[1] = val[x][1], tmp[2] = val[y][0], tmp[3] = val[y][1];
      sort(tmp, tmp + 4);
      val[x][0] = tmp[0], val[x][1] = Info();
      for (int i = 1; i < 4; ++i) {
        if (tmp[i].c && tmp[i].c != tmp[0].c) {
          val[x][1] = tmp[i];
          break;
        }
      }
    }
  }

  inline void Solve() {
    sort(seq + 1, seq + m + 1, [&](const int &x, const int &y) {
      return p[x] < p[y];
    });
    for (int i = m; i > 1; --i) {
      seq[++m] = LCA(seq[i], seq[i - 1]);
    }
    sort(seq + 1, seq + m + 1, [&](const int &x, const int &y) {
      return p[x] < p[y];
    });
    m = unique(seq + 1, seq + m + 1) - seq - 1, top = 0;
    for (int i = 1; i <= m; ++i) {
      for (; top && !(p[sta[top]] <= p[seq[i]] && q[sta[top]] >= q[seq[i]]); --top);
      if (top) {
        adj[sta[top]].pb(seq[i]);
      }
      sta[++top] = seq[i];
    }
    DP(seq[1]);
    for (int i = 1; i <= m; ++i) {
      adj[seq[i]].clear(), bel[seq[i]] = 0;
    }
  }
} A, B;

inline void Solve() {
  for (int i = 1; i <= m; ++i) {
    len[seq[i]] += A.dis[seq[i]] - B.dis[seq[i]];
  }
  A.Solve();
}

inline void Solve(int x, int s) {
  int c;
  B.FindRoot(x, 0, s, c);
  vis[x = c] = true, seq[m = 1] = x, bel[x] = x, len[x] = 0;
  for (int i = B.hed[x]; i; i = B.e[i].v) {
    int y = B.e[i].p;
    if (!vis[y]) {
      B.DFS(y, x, y, B.e[i].w);
    }
  }
  Solve();
  for (int i = B.hed[x]; i; i = B.e[i].v) {
    int y = B.e[i].p;
    if (!vis[y]) {
      Solve(y, siz[y]);
    }
  }
}

int main() {
#ifdef wxh010910
  freopen("d.in", "r", stdin);
#endif
  Read(n);
  for (int i = 1; i < n; ++i) {
    int x, y;
    LL w;
    Read(x), Read(y), Read(w);
    A.AddEdge(x, y, w);
  }
  for (int i = 1; i < n; ++i) {
    int x, y;
    LL w;
    Read(x), Read(y), Read(w);
    B.AddEdge(x, y, w);
  }
  A.Build(), B.Build(), Solve(1, n);
  for (int i = 1; i <= n; ++i) {
    CheckMax(ans, A.dis[i] - B.dis[i] << 1);
  }
  printf("%lld\n", ans >> 1);
#ifdef wxh010910
  Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  return 0;
}

green

注意到区间之间一定是包含或者相离,不然无解。这样可以建出树结构,记 f(n) f ( n ) 表示满足 Li=1(in+1) L i = 1 ( i ≠ n + 1 ) 的排列个数, soni s o n i 表示 i i 的儿子个数,那么答案就是 f(soni)

考虑如何求 f(n) f ( n ) ,由于问题的对称性,可以将下标与值互换,变成询问有多少个排列任意一个长度不为 1 1 的连续区间都经过最大值。

考虑删除 1 这个值,如果剩下的序列合法,那么就是在 f(n1) f ( n − 1 ) 插入一个与 2 2 不相邻的数,方案数是 n1

另一种情况,考虑生成的一个极长连续段,假设它的值域为 [x,x+l1] [ x , x + l − 1 ] ,那么一定有 x>2,x+l1<n+1 x > 2 , x + l − 1 < n + 1 ,那么选取 x x 的方案数就是 nl1 ,而这一段内部排列的方案数是 f(l) f ( l ) (将最大最小对称一下),将这一段看成整体,外部的方案数是 f(nl) f ( n − l ) ,所以有递推式:

f(n)=(n1)f(n1)+n2i=2(i1)f(i)f(ni) f ( n ) = ( n − 1 ) f ( n − 1 ) + ∑ i = 2 n − 2 ( i − 1 ) f ( i ) f ( n − i )

分治NTT优化即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 131075;
const int M = 20;
const int G = 3;
const int mod = 998244353;

int D, L, W[M], R[N];

inline int Qow(int x, int y) {
  int r = 1;
  for (; y; y >>= 1, x = 1LL * x * x % mod) {
    if (y & 1) {
      r = 1LL * r * x % mod;
    }
  }
  return r;
}

inline void DFT(int *a) {
  for (int i = 0; i < D; ++i) {
    if (i < R[i]) {
      swap(a[i], a[R[i]]);
    }
  }
  for (int i = 1, l = L - 1; i < D; i <<= 1, --l) {
    for (int j = 0; j < D; j += i << 1) {
      for (int k = 0, w = 1, u, v; k < i; ++k, w = 1LL * w * W[l] % mod) {
        u = a[j + k], v = 1LL * w * a[j + k + i] % mod;
        a[j + k] = (u + v) % mod, a[j + k + i] = (u - v + mod) % mod;
      }
    }
  }
}

inline vector <int> Mul(vector <int> a, vector <int> b) {
  static int x[N], y[N];
  int n = a.size(), m = b.size();
  for (D = 1, L = 0; D < n + m - 1; D <<= 1, ++L);
  for (int i = 1; i < D; ++i) {
    R[i] = (R[i >> 1] >> 1) | ((i & 1) << L - 1);
  }
  W[0] = Qow(G, mod - 1 >> L);
  for (int i = 1; i < L; ++i) {
    W[i] = 1LL * W[i - 1] * W[i - 1] % mod;
  }
  for (int i = 0; i < D; ++i) {
    x[i] = i < n ? a[i] : 0, y[i] = i < m ? b[i] : 0;
  }
  DFT(x), DFT(y);
  for (int i = 0; i < D; ++i) {
    x[i] = 1LL * x[i] * y[i] % mod;
  }
  W[0] = Qow(W[0], mod - 2);
  for (int i = 1; i < L; ++i) {
    W[i] = 1LL * W[i - 1] * W[i - 1] % mod;
  }
  DFT(x);
  for (int i = 0, v = Qow(D, mod - 2); i < D; ++i) {
    x[i] = 1LL * x[i] * v % mod;
  }
  return vector <int> (x, x + n + m - 1);
}

int n, ans, top, a[N], b[N], f[N], sta[N];

inline void Solve(int l, int r) {
  if (l == r) {
    f[l] = (1LL * f[l - 1] * (l - 1) + f[l]) % mod;
    return ;
  }
  int mid = l + r >> 1;
  Solve(l, mid);
  vector <int> a, b;
  for (int i = l; i <= mid; ++i) {
    a.pb(f[i]), b.pb(1LL * f[i] * (i - 1) % mod);
  }
  a = Mul(a, b);
  for (int i = max(mid + 1, l << 1); i <= r; ++i) {
    f[i] = (f[i] + a[i - (l << 1)]) % mod;
  }
  if (l != 2) {
    a.clear(), b.clear();
    for (int i = 2; i <= min(l - 1, r - l); ++i) {
      a.pb(f[i]);
    }
    for (int i = l; i <= mid; ++i) {
      b.pb(f[i]);
    }
    a = Mul(a, b);
    for (int i = max(l + 2, mid + 1); i <= r; ++i) {
      f[i] = (1LL * a[i - l - 2] * (i - 2) + f[i]) % mod;
    }
  }
  Solve(mid + 1, r);
}

int Main() {
  for (int i = 1; i <= n; ++i) {
    Read(a[i]), b[i] = 0;
  }
  if (a[n] != n) {
    puts("0");
    return 0;
  }
  ans = 1, top = 0;
  for (int i = n; ~i; --i) {
    for (; top && sta[top] - a[sta[top]] >= i; ++b[sta[--top]]);
    if (top && sta[top] - a[sta[top]] > i - a[i]) {
      puts("0");
      return 0;
    }
    sta[++top] = i;
  }
  for (int i = 1; i <= n; ++i) {
    ans = 1LL * ans * f[b[i]] % mod;
  }
  printf("%d\n", ans);
  return 0;
}

int main() {
#ifdef wxh010910
  freopen("d.in", "r", stdin);
#endif
  int T;
  for (Read(T), Read(n), f[0] = 1, f[1] = 2, Solve(2, n - 1); T; --T) {
    Main();
  }
#ifdef wxh010910
  Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  return 0;
}

Day 2

juice

将所有果汁按照 d d 从大到小排序,对于每次询问二分,那么剩下的部分就可以贪心选取了,用主席树维护即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 100005;
const int M = 6000005;

struct Info {
  int d, p, l;

  bool operator < (const Info &b) const {
    return d > b.d;
  }
} a[N];

struct Node {
  int l, r;
  LL v, s;
} e[M];

int n, m, mxp, tot, rot[N];

inline void Modify(int &x, int y, int l, int r, int p, int v) {
  e[x = ++tot] = e[y], e[x].v += v, e[x].s += 1LL * p * v;
  if (l == r) {
    return ;
  }
  int mid = l + r >> 1;
  if (p <= mid) {
    Modify(e[x].l, e[y].l, l, mid, p, v);
  } else {
    Modify(e[x].r, e[y].r, mid + 1, r, p, v);
  }
}

inline bool Check(int x, int l, int r, LL vol, LL pri) {
  if (e[x].v < vol || pri / l < vol) {
    return false;
  }
  if (l == r) {
    return true;
  }
  int mid = l + r >> 1;
  if (vol <= e[e[x].l].v) {
    return Check(e[x].l, l, mid, vol, pri);
  } else {
    return Check(e[x].r, mid + 1, r, vol - e[e[x].l].v, pri - e[e[x].l].s);
  }
}

int main() {
#ifdef wxh010910
  freopen("d.in", "r", stdin);
#endif
  Read(n), Read(m);
  for (int i = 1; i <= n; ++i) {
    Read(a[i].d), Read(a[i].p), Read(a[i].l);
    CheckMax(mxp, a[i].p);
  }
  sort(a + 1, a + n + 1);
  for (int i = 1; i <= n; ++i) {
    Modify(rot[i], rot[i - 1], 1, mxp, a[i].p, a[i].l);
  }
  for (int i = 1; i <= m; ++i) {
    LL pri, vol;
    Read(pri), Read(vol);
    if (!Check(rot[n], 1, mxp, vol, pri)) {
      puts("-1");
    } else {
      int l = 1, r = n - 1, ret = n;
      while (l <= r) {
        int mid = l + r >> 1;
        if (Check(rot[mid], 1, mxp, vol, pri)) {
          ret = mid, r = mid - 1;
        } else {
          l = mid + 1;
        }
      }
      printf("%d\n", a[ret].d);
    }
  }
#ifdef wxh010910
  Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  return 0;
}

trie

做法是假的

f(i) 表示 i i <script type="math/tex" id="MathJax-Element-43">i</script> 是逗号,其子树最小值最大可以是多少,暴力转移就行了,常数很小可以通过,具体细节参考代码。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return b < a ? a = b, true : false;
}

const int N = 405;

vector <int> adj[N];
string inf, f[N];
char s[N];
int n, m;

bool operator < (const string &a, const string &b) {
  return a.length() != b.length() ? a.length() < b.length() : b > a;
}

inline string Leq(string s, string t) {
  if (s[0] == '0' || s.length() > t.length()) {
    return "";
  }
  if (s.length() < t.length()) {
    for (int i = 0; i < s.length(); ++i) {
      if (s[i] == '?') {
        s[i] = '9';
      }
    }
    return s;
  }
  string x = "x", y = "y";
  for (int i = 0; i < s.length(); ++i) {
    if (s[i] != '?') {
      if (s[i] < t[i]) {
        x = max(x, y) + s[i], y = "x";
      } else if (s[i] == t[i]) {
        x += s[i], y += s[i];
      } else {
        x += s[i], y = "x";
      }
    } else {
      x += "9";
      if (t[i] != '0') {
        CheckMax(x, y + (char)(t[i] - 1));
      }
      y += t[i];
    }
  }
  if (x[0] == 'x' || x[1] == '0') {
    return "";
  }
  x.erase(x.begin());
  return x;
}

inline string Geq(string s, string t) {
  if (s[0] == '0' || s.length() < t.length()) {
    return "";
  }
  if (s.length() > t.length()) {
    for (int i = 0; i < s.length(); ++i) {
      if (s[i] == '?') {
        s[i] = i ? '0' : '1';
      }
    }
    return s;
  }
  string x = "y", y = "x";
  for (int i = 0; i < s.length(); ++i) {
    if (s[i] != '?') {
      if (s[i] > t[i]) {
        x = (y > x ? x : y) + s[i], y = "y";
      } else if (s[i] == t[i]) {
        x += s[i], y += s[i];
      } else {
        x += s[i], y = "y";
      }
    } else {
      x += "0";
      if (t[i] != '9') {
        if (x > y + (char)(t[i] + 1)) {
          x = y + (char)(t[i] + 1);
        }
      }
      y += t[i];
    }
  }
  if (x[0] == 'y' || x[1] == '0') {
    return "";
  }
  x.erase(x.begin());
  return x;
}


inline string U(int x, string str) {
  string ans = "";
  if (str != "" && f[x] != "") {
    ans = Leq(str, f[x]);
  }
  if (s[x] != ',') {
    str += s[x];
    string ret = inf;
    for (auto y : adj[x]) {
      CheckMin(ret, U(y, str));
    }
    CheckMax(ans, ret);
  }
  return ans;
}

inline void U(int x) {
  if (x > n) {
    return ;
  }
  for (auto y : adj[x]) {
    U(y);
  }
  if (!isdigit(s[x])) {
    f[x] = inf;
    for (auto y : adj[x]) {
      CheckMin(f[x], U(y, ""));
    }
  }
}

inline bool C(int x, string str, string lst) {
  if (str != "" && str[0] == '0') {
    return false;
  }
  if (f[x] != "") {
    string tmp = Geq(str, lst);
    if (tmp != "" && tmp < f[x]) {
      return true;
    }
  }
  if (s[x] == ',') {
    return false;
  }
  str += s[x];
  for (auto y : adj[x]) {
    if (!C(y, str, lst)) {
      return false;
    }
  }
  return true;
}

inline void D(int x, string str, string lst) {
  if (x > n) {
    return ;
  }
  if (s[x] == '?') {
    if (lst < str && str < f[x]) {
      s[x] = ',';
    } else {
      for (s[x] = '0'; !C(x, str, lst); ++s[x]);
    }
  }
  if (s[x] == ',') {
    lst = str, str = "";
  } else {
    str += s[x];
  }
  for (auto y : adj[x]) {
    D(y, str, lst);
  }
}

int Main() {
  scanf("%s", s + 1), n = strlen(s + 1), m = n, inf = "";
  for (int i = 0; i <= n; ++i) {
    adj[i].clear(), f[i] = "", inf += "9";
  }
  s[0] = ',';
  for (int i = 1, x; i <= n; ++i) {
    Read(x), adj[x].pb(i);
  }
  for (int i = 1; i <= n; ++i) {
    if (adj[i].empty()) {
      adj[i].pb(++m), s[m] = ',', f[m] = inf;
    }
  }
  U(0);
  if (f[0] == "") {
    puts("failed");
    return 0;
  }
  D(0, "", "0");
  for (int i = 1; i <= n; ++i) {
    putchar(s[i]);
  }
  putchar(10);
  return 0;
}

int main() {
#ifdef wxh010910
  freopen("d.in", "r", stdin);
#endif
  int T;
  for (Read(T); T; --T) {
    Main();
  }
#ifdef wxh010910
  Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  return 0;
}

placement

task 1

爆搜。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int inf = 0x3f3f3f3f;

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

inline void Update() {
  int ret = 0;
  for (int i = 0; i < n; ++i) {
    ret += run[i][per[i]];
  }
  for (int i = 0; i < n; ++i) {
    for (auto j : adj[i]) {
      ret += mov[per[i]][per[j]];
    }
  }
  if (CheckMin(ans, ret)) {
    bes = per;
  }
}

inline void DFS(int x) {
  if (x == n) {
    Update();
    return ;
  }
  for (per[x] = 0; per[x] < m; DFS(x + 1), ++per[x]);
}

int main() {
  freopen("placement1.in", "r", stdin);
  freopen("placement1.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), ans = inf, DFS(0);
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 2

爆搜。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int inf = 0x3f3f3f3f;

struct Event {
  int o, v, t;

  Event(int o = 0, int v = 0, int t = 0):o(o), v(v), t(t) {}

  bool operator < (const Event &b) const {
    return t > b.t;
  }
};

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

inline void Update() {
  vector <priority_queue <int, vector <int>, greater <int>>> que(m);
  priority_queue <Event> q;
  vector <bool> cur(m);
  vector <int> deg(n);
  int ret = 0;
  for (int i = 0; i < n; ++i) {
    for (auto j : adj[i]) {
      ++deg[j];
    }
  }
  for (int i = 0; i < n; ++i) {
    if (!deg[i]) {
      if (!cur[per[i]]) {
        cur[per[i]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
      } else {
        que[per[i]].push(i);
      }
    }
  }
  while (!q.empty()) {
    Event e = q.top();
    q.pop();
    int x = e.v;
    ret = e.t;
    if (e.o) {
      for (auto y : adj[x]) {
        q.push(Event(0, y, ret + mov[per[x]][per[y]]));
      }
      cur[per[x]] = false;
      if (!que[per[x]].empty()) {
        int i = que[per[x]].top();
        que[per[x]].pop();
        cur[per[x]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
      }
    } else {
      if (!--deg[x]) {
        if (!cur[per[x]]) {
          cur[per[x]] = true, q.push(Event(1, x, run[x][per[x]] + ret));
        } else {
          que[per[x]].push(x);
        }
      }
    }
  }
  if (CheckMin(ans, ret)) {
    bes = per;
  }
}

inline void DFS(int x) {
  if (x == n) {
    Update();
    return ;
  }
  for (per[x] = 0; per[x] < m; DFS(x + 1), ++per[x]);
}

int main() {
  freopen("placement2.in", "r", stdin);
  freopen("placement2.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), ans = inf, DFS(0);
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 3

背包dp。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 110;
const int lim = 106;

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

int f[N][N][N][N];

int main() {
  freopen("placement3.in", "r", stdin);
  freopen("placement3.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  f[0][0][0][0] = 1, per.resize(n);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j <= lim; ++j) {
      for (int k = 0; k <= lim; ++k) {
        for (int l = 0; l <= lim; ++l) {
          if (f[i][j][k][l]) {
            if (j + run[i][0] <= lim) {
              f[i + 1][j + run[i][0]][k][l] = 1;
            }
            if (k + run[i][1] <= lim) {
              f[i + 1][j][k + run[i][1]][l] = 2;
            }
            if (l + run[i][2] <= lim) {
              f[i + 1][j][k][l + run[i][2]] = 3;
            }
          }
        }
      }
    }
  }
  for (int i = 0; i <= lim; ++i) {
    for (int j = 0; j <= lim; ++j) {
      for (int k = 0; k <= lim; ++k) {
        if (f[n][i][j][k]) {
          ans = lim;
          for (int t = n - 1; ~t; --t) {
            per[t] = f[t + 1][i][j][k] - 1;
            if (f[t + 1][i][j][k] == 1) {
              i -= run[t][0];
            } else if (f[t + 1][i][j][k] == 2) {
              j -= run[t][1];
            } else {
              k -= run[t][2];
            }
          }
          i = j = k = lim;
        }
      }
    }
  }
  bes = per;
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 4

对三条链分别dp。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 400;
const int inf = 0x3f3f3f3f;

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

int f[N][N], g[N][N];

inline void Solve(int l, int r) {
  for (int i = 0; i < m; ++i) {
    f[l][i] = run[l][i];
  }
  for (int i = l + 1; i < r; ++i) {
    for (int j = 0; j < m; ++j) {
      f[i][j] = inf;
      for (int k = 0; k < m; ++k) {
        if (CheckMin(f[i][j], f[i - 1][k] + mov[k][j])) {
          g[i][j] = k;
        }
      }
      f[i][j] += run[i][j];
    }
  }
  int pos = -1, ret = inf;
  for (int i = 0; i < m; ++i) {
    if (CheckMin(ret, f[r - 1][i])) {
      pos = i;
    }
  }
  ans += ret;
  for (int i = r - 1; i >= l; --i) {
    per[i] = pos, pos = g[i][pos];
  }
}

int main() {
  freopen("placement4.in", "r", stdin);
  freopen("placement4.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), Solve(0, 133), Solve(133, 266), Solve(266, 399), bes = per;
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 5

状压dp。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 3125;
const int inf = 0x3f3f3f3f;
const int base[] = {1, 5, 25, 125, 625, 3125};

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

int f[N][N], g[N][N];

int main() {
  freopen("placement5.in", "r", stdin);
  freopen("placement5.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[y].pb(x);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n);
  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < m; ++j) {
      f[4][i] += run[4 - j][i / base[j] % m];
      for (auto k : adj[4 - j]) {
        f[4][i] += mov[i / base[4 - k] % m][i / base[j] % m];
      }
    }
  }
  for (int i = 5; i < n; ++i) {
    for (int j = 0; j < N; ++j) {
      f[i][j] = inf;
    }
  }
  for (int i = 4; i < n - 1; ++i) {
    for (int j = 0; j < N; ++j) {
      for (int k = 0; k < m; ++k) {
        int ret = f[i][j] + run[i + 1][k], l = j % base[m - 1] * m + k;
        for (auto x : adj[i + 1]) {
          ret += mov[j / base[i - x] % m][k];
        }
        if (CheckMin(f[i + 1][l], ret)) {
          g[i + 1][l] = j;
        }
      }
    }
  }
  ans = inf;
  int cur = -1;
  for (int i = 0; i < N; ++i) {
    if (CheckMin(ans, f[n - 1][i])) {
      cur = i;
    }
  }
  for (int i = n - 1; i > 4; --i) {
    per[i] = cur % m, cur = g[i][cur];
  }
  for (int i = 0; i < m; ++i) {
    per[4 - i] = cur / base[i] % m;
  }
  bes = per;
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 6

最小割。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 505;
const int M = 100005;
const int inf = 0x3f3f3f3f;

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

struct Edge {
  int p, v, w;

  Edge(int p = 0, int v = 0, int w = 0):p(p), v(v), w(w) {}
} e[M];

int S, T, cnt = 1, cur[N], dis[N], hed[N];

inline void AddEdge(int x, int y, int w) {
  e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
  e[++cnt] = Edge(x, hed[y], 0), hed[y] = cnt;
}

inline bool BFS() {
  queue <int> q;
  for (int i = S; i <= T; ++i) {
    dis[i] = 0;
  }
  for (q.push(S), dis[S] = 1; !q.empty(); q.pop()) {
    int x = q.front();
    for (int i = hed[x]; i; i = e[i].v) {
      if (e[i].w && !dis[e[i].p]) {
        dis[e[i].p] = dis[x] + 1, q.push(e[i].p);
      }
    }
  }
  return dis[T];
}

inline int DFS(int x, int f) {
  if (x == T) {
    return f;
  }
  int r = 0, w;
  for (int &i = cur[x]; i; i = e[i].v) {
    if (e[i].w && dis[e[i].p] == dis[x] + 1) {
      w = DFS(e[i].p, min(f - r, e[i].w));
      e[i].w -= w, e[i ^ 1].w += w, r += w;
      if (r == f) {
        return r;
      }
    }
  }
  dis[x] = -1;
  return r;
}

inline int Dinic() {
  int r = 0;
  while (BFS()) {
    for (int i = S; i <= T; ++i) {
      cur[i] = hed[i];
    }
    r += DFS(S, inf);
  }
  return r;
}

int main() {
  freopen("placement6.in", "r", stdin);
  freopen("placement6.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), T = n + 1;
  for (int i = 0; i < n; ++i) {
    AddEdge(S, i + 1, run[i][0]), AddEdge(i + 1, T, run[i][1]);
  }
  for (int i = 0; i < n; ++i) {
    for (auto j : adj[i]) {
      AddEdge(i + 1, j + 1, mov[1][0]), AddEdge(j + 1, i + 1, mov[0][1]);
    }
  }
  ans = Dinic();
  for (int i = 0; i < n; ++i) {
    per[i] = dis[i + 1] == 2;
  }
  bes = per;
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 7

二分图匹配。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 1105;
const int M = 100005;
const int lim = 1014;
const int inf = 0x3f3f3f3f;

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

struct Edge {
  int p, v, w;

  Edge(int p = 0, int v = 0, int w = 0):p(p), v(v), w(w) {}
} e[M];

int S, T, cnt = 1, cur[N], dis[N], hed[N], edg[N][N];

inline void AddEdge(int x, int y, int w) {
  e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
  e[++cnt] = Edge(x, hed[y], 0), hed[y] = cnt;
}

inline bool BFS() {
  queue <int> q;
  for (int i = S; i <= T; ++i) {
    dis[i] = 0;
  }
  for (q.push(S), dis[S] = 1; !q.empty(); q.pop()) {
    int x = q.front();
    for (int i = hed[x]; i; i = e[i].v) {
      if (e[i].w && !dis[e[i].p]) {
        dis[e[i].p] = dis[x] + 1, q.push(e[i].p);
      }
    }
  }
  return dis[T];
}

inline int DFS(int x, int f) {
  if (x == T) {
    return f;
  }
  int r = 0, w;
  for (int &i = cur[x]; i; i = e[i].v) {
    if (e[i].w && dis[e[i].p] == dis[x] + 1) {
      w = DFS(e[i].p, min(f - r, e[i].w));
      e[i].w -= w, e[i ^ 1].w += w, r += w;
      if (r == f) {
        return r;
      }
    }
  }
  dis[x] = -1;
  return r;
}

inline int Dinic() {
  int r = 0;
  while (BFS()) {
    for (int i = S; i <= T; ++i) {
      cur[i] = hed[i];
    }
    r += DFS(S, inf);
  }
  return r;
}

int main() {
  freopen("placement7.in", "r", stdin);
  freopen("placement7.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), T = n + m + 1;
  for (int i = 0; i < n; ++i) {
    AddEdge(S, i + 1, 1);
  }
  for (int i = 0; i < m; ++i) {
    AddEdge(i + n + 1, T, 1);
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (run[i][j] <= lim) {
        AddEdge(i + 1, j + n + 1, 1), edg[i][j] = cnt;
      }
    }
  }
  if (Dinic() == n) {
    ans = lim;
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (run[i][j] <= lim && e[edg[i][j]].w) {
        per[i] = j;
        break;
      }
    }
  }
  bes = per;
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 8

分层图,对于每层二分答案之后就是二分图匹配了。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 655;
const int M = 100005;
const int inf = 0x3f3f3f3f;

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

struct Edge {
  int p, v, w;

  Edge(int p = 0, int v = 0, int w = 0):p(p), v(v), w(w) {}
} e[M];

int S, T, cnt = 1, cur[N], dis[N], hed[N], edg[N][N];

inline void AddEdge(int x, int y, int w) {
  e[++cnt] = Edge(y, hed[x], w), hed[x] = cnt;
  e[++cnt] = Edge(x, hed[y], 0), hed[y] = cnt;
}

inline bool BFS() {
  queue <int> q;
  for (int i = S; i <= T; ++i) {
    dis[i] = 0;
  }
  for (q.push(S), dis[S] = 1; !q.empty(); q.pop()) {
    int x = q.front();
    for (int i = hed[x]; i; i = e[i].v) {
      if (e[i].w && !dis[e[i].p]) {
        dis[e[i].p] = dis[x] + 1, q.push(e[i].p);
      }
    }
  }
  return dis[T];
}

inline int DFS(int x, int f) {
  if (x == T) {
    return f;
  }
  int r = 0, w;
  for (int &i = cur[x]; i; i = e[i].v) {
    if (e[i].w && dis[e[i].p] == dis[x] + 1) {
      w = DFS(e[i].p, min(f - r, e[i].w));
      e[i].w -= w, e[i ^ 1].w += w, r += w;
      if (r == f) {
        return r;
      }
    }
  }
  dis[x] = -1;
  return r;
}

inline int Dinic() {
  int r = 0;
  while (BFS()) {
    for (int i = S; i <= T; ++i) {
      cur[i] = hed[i];
    }
    r += DFS(S, inf);
  }
  return r;
}

inline bool Check(int l, int r, int mid) {
  T = r - l + m + 1, cnt = 1;
  for (int i = S; i <= T; ++i) {
    hed[i] = 0;
  }
  for (int i = 0; i < r - l; ++i) {
    AddEdge(S, i + 1, 1);
  }
  for (int i = 0; i < m; ++i) {
    AddEdge(i + r - l + 1, T, 1);
  }
  for (int i = l; i < r; ++i) {
    for (int j = 0; j < m; ++j) {
      if (run[i][j] <= mid) {
        AddEdge(i - l + 1, j + r - l + 1, 1), edg[i][j] = cnt;
      }
    }
  }
  if (Dinic() != r - l) {
    return false;
  }
  for (int i = l; i < r; ++i) {
    for (int j = 0; j < m; ++j) {
      if (run[i][j] <= mid && e[edg[i][j]].w) {
        per[i] = j;
      }
    }
  }
  return true;
}

inline void Solve(int l, int r) {
  int L = 1, R = 10000, ret = R;
  while (L <= R) {
    int mid = L + R >> 1;
    if (Check(l, r, mid)) {
      ret = mid, R = mid - 1;
    } else {
      L = mid + 1;
    }
  }
  ans += ret + 1;
}

int main() {
  freopen("placement8.in", "r", stdin);
  freopen("placement8.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), ans = -1;
  Solve(0, 1);
  for (int i = 1, j = i + 50; i < n - 1; Solve(i, j), i += 50, j += 50);
  Solve(n - 1, n);
  bes = per;
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 9

爬山。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int inf = 0x3f3f3f3f;

struct Event {
  int o, v, t;

  Event(int o = 0, int v = 0, int t = 0):o(o), v(v), t(t) {}

  bool operator < (const Event &b) const {
    return t > b.t;
  }
};

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

inline int Calc() {
  vector <priority_queue <int, vector <int>, greater <int>>> que(m);
  priority_queue <Event> q;
  vector <bool> cur(m);
  vector <int> deg(n);
  int ret = 0;
  for (int i = 0; i < n; ++i) {
    for (auto j : adj[i]) {
      ++deg[j];
    }
  }
  for (int i = 0; i < n; ++i) {
    if (!deg[i]) {
      if (!cur[per[i]]) {
        cur[per[i]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
      } else {
        que[per[i]].push(i);
      }
    }
  }
  while (!q.empty()) {
    Event e = q.top();
    q.pop();
    int x = e.v;
    ret = e.t;
    if (e.o) {
      for (auto y : adj[x]) {
        q.push(Event(0, y, ret + mov[per[x]][per[y]]));
      }
      cur[per[x]] = false;
      if (!que[per[x]].empty()) {
        int i = que[per[x]].top();
        que[per[x]].pop();
        cur[per[x]] = true, q.push(Event(1, i, run[i][per[i]] + ret));
      }
    } else {
      if (!--deg[x]) {
        if (!cur[per[x]]) {
          cur[per[x]] = true, q.push(Event(1, x, run[x][per[x]] + ret));
        } else {
          que[per[x]].push(x);
        }
      }
    }
  }
  return ret;
}

int main() {
  freopen("placement9.in", "r", stdin);
  freopen("placement9.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), ans = inf, srand(time(0));
  for (int t = 0; t < 20; ++t) {
    for (int i = 0; i < n; ++i) {
      per[i] = rand() % m;
    }
    for (int i = 0; i < 2000; ++i) {
      int x = rand() % n, lst = inf, val = -1;
      for (int j = 0; j < m; ++j) {
        per[x] = j;
        int cur = Calc();
        if (CheckMin(lst, cur)) {
          val = j;
        }
      }
      per[x] = val;
      if (CheckMin(ans, lst)) {
        bes = per;
        Debug("ans = %d\n", ans);
        for (int j = 0; j < n; ++j) {
          Debug("%d%c", bes[j] + 1, j == n - 1 ? '\n' : ' ');
        }
      }
    }
    Debug("t = %d\n", t);
  }
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
task 10

爬山。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int inf = 0x3f3f3f3f;

vector <vector <int>> adj, mov, run;
vector <int> bes, per;
int n, m, o, q, ans;

inline int Calc() {
  int ret = 0;
  for (int i = 0; i < n; ++i) {
    ret += run[i][per[i]];
  }
  for (int i = 0; i < n; ++i) {
    for (auto j : adj[i]) {
      ret += mov[per[i]][per[j]];
    }
  }
  return ret;
}

int main() {
  freopen("placement10.in", "r", stdin);
  freopen("placement10.out", "w", stdout);

  Read(n), Read(q), Read(m), Read(o);
  adj.resize(n), run.resize(n), mov.resize(m);
  for (int i = 0, x, y; i < q; ++i) {
    Read(x), Read(y), --x, --y;
    adj[x].pb(y);
  }
  for (int i = 0; i < n; ++i) {
    run[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(run[i][j]);
    }
  }
  for (int i = 0; i < m; ++i) {
    mov[i].resize(m);
    for (int j = 0; j < m; ++j) {
      Read(mov[i][j]);
    }
  }
  per.resize(n), ans = inf, srand(time(0));
  for (int t = 0; t < 10; ++t) {
    for (int i = 0; i < n; ++i) {
      per[i] = rand() % m;
    }
    int lst = Calc();
    for (int i = 0; i < 100000; ++i) {
      int x = rand() % n, y = rand() % m, z = per[x];
      per[x] = y;
      int cur = Calc();
      if (!CheckMin(lst, cur)) {
        per[x] = z;
      } else {
        if (CheckMin(ans, cur)) {
          bes = per;
        }
      }
    }
  }
  Debug("%d\n", ans);
  for (int i = 0; i < n; ++i) {
    printf("%d%c", bes[i] + 1, i == n - 1 ? '\n' : ' ');
  }
  return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值