目录
H. Genshin Impact Startup Forbidden III
K. Points on the Number Axis B
I. Colorful Tree
估计还会补D,I不补了,补不动了
H. Genshin Impact Startup Forbidden III
对于一个有鱼的池塘,有周围与自己本身五个关键位置可以捕获当前位位置的鱼。把这些位置存储到 map中。用四进制数 S 表示每块池塘中剩余的鱼的数目,dp[S] 表示达成该状态最少的炸弹数。枚举所有的关键位置,计算状态的转移。
#define PII pair<int,int>
const int inf = 0x3f3f3f3f3f3f3f3f, N = 1e5 + 5, mod = 1e9 + 7;
map < PII, vector<int>>mp;
PII pos[5] = { {0,0},{0,1},{1,0},{-1,0},{0,-1} };
signed main()
{ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);vector<int>pow(15);pow[0] = 1;for (int i = 1; i < 11; i++) {pow[i] = pow[i - 1] * 4;}int n, m, k;cin >> n >> m >> k;vector<int>val;int res = 0;for (int I = 0; I < k; I++){int x, y, a;cin >> x >> y >> a;val.push_back(a);res += int(a*pow[I]);for (int i = 0; i < 5; i++){int xx = x + pos[i].first, yy = y + pos[i].second;if (xx <= 0 || xx > n || yy <= 0 || yy > m) continue;mp[{xx, yy}].push_back(I);}}auto check = [&](int x){for (int i = 0; i < k; i++) {if (x % 4 > val[i]) return true;x /= 4;}return false;};auto check2 = [&](int x, int y){for (int i = 0; i < y; i++) {x /= 4;}if (x % 4 == val[y]) return true;return false;};vector<int>dp(int(pow[ k]),inf);dp[0] = 0;for (int i = 0; i<int(pow[k]); i++) {if (check(i)) continue;for (auto w : mp) {vector<int>& tmp = w.second;int t = i;for (auto ww : tmp) {if (check2(t,ww)) continue;t += int(pow[ww]);}dp[t] = min(dp[t], dp[i] + 1);}}cout << dp[res];
}
K. Points on the Number Axis B
#define int long long//__int128 2^127-1(GCC)
#define PII pair<int,int>
const int inf = 0x3f3f3f3f3f3f3f3f, N = 1e6 + 5, mod = 998244353;
void add(int& x, int y) {x += y;if (x >= mod) x -= mod;
}
int binpow(int a, int b) {if (!b) return 1;if (b & 1) return 1ll * a * binpow(a, b - 1) % mod;return binpow(1ll * a * a % mod, b >> 1);
}
int n, a[N], dp[N];
signed main()
{ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);cin >> n;for (int i = 0; i < n; i++) cin >> a[i];dp[0] = 1;for (int i = 1; i < n; i++) {dp[i] = 1ll * dp[i - 1] * (i + i - 1) % mod;dp[i] = 1ll * dp[i] * binpow(i + i, mod - 2) % mod;}int ans = 0;for (int i = 0; i < n; i++) add(ans, 1ll * a[i] * dp[i] % mod * dp[n - i - 1] % mod);cout << ans;
}
I. Colorful Tree
本代码参考 jiangly 258662407
大致思路是先找到白变黑的顺序将其放再vector<vector<int>>vec(q + 1);
然后黑变白就是其相反
然后按照顺序去维护每一棵树的直径,同时用并查集的方式存储每一棵树的直径,每次按事件顺序加点的时候进行更新,然后维护一个最大值更新一下就行了
新加入一棵树,且新加入的直径是(x,y)后,新直径的端点一定是(u,x)(u,y)(u,v)(v,x)(v,y)(x,y)
#define PII pair<int,int>
const int inf = 0x3f3f3f3f3f3f3f3f, N = 1500 + 11, mod = 1e9 + 7;
struct HLD {int n;std::vector<int> siz, top, dep, parent, in, out, seq;std::vector<std::vector<int>> adj;int cur;HLD() {}HLD(int n) {init(n);}void init(int n) {this->n = n;siz.resize(n);top.resize(n);dep.resize(n);parent.resize(n);in.resize(n);out.resize(n);seq.resize(n);cur = 0;adj.assign(n, {});}void addEdge(int u, int v) {adj[u].push_back(v);adj[v].push_back(u);}void work(int root = 0) {top[root] = root;dep[root] = 0;parent[root] = -1;dfs1(root);dfs2(root);}void dfs1(int u) {if (parent[u] != -1) {adj[u].erase(std::find(adj[u].begin(), adj[u].end(), parent[u]));}siz[u] = 1;for (auto& v : adj[u]) {parent[v] = u;dep[v] = dep[u] + 1;dfs1(v);siz[u] += siz[v];if (siz[v] > siz[adj[u][0]]) {std::swap(v, adj[u][0]);}}}void dfs2(int u) {in[u] = cur++;seq[in[u]] = u;for (auto v : adj[u]) {top[v] = v == adj[u][0] ? top[u] : v;dfs2(v);}out[u] = cur;}int lca(int u, int v) {while (top[u] != top[v]) {if (dep[top[u]] > dep[top[v]]) {u = parent[top[u]];}else {v = parent[top[v]];}}return dep[u] < dep[v] ? u : v;}int dist(int u, int v) {return dep[u] + dep[v] - 2 * dep[lca(u, v)];}int jump(int u, int k) {if (dep[u] < k) {return -1;}int d = dep[u] - k;while (dep[top[u]] > d) {u = parent[top[u]];}return seq[in[u] - dep[u] + d];}bool isAncester(int u, int v) {return in[u] <= in[v] && in[v] < out[u];}int rootedParent(int u, int v) {std::swap(u, v);if (u == v) {return u;}if (!isAncester(u, v)) {return parent[u];}auto it = std::upper_bound(adj[u].begin(), adj[u].end(), v, [&](int x, int y) {return in[x] < in[y];}) - 1;return *it;}int rootedSize(int u, int v) {if (u == v) {return n;}if (!isAncester(v, u)) {return siz[v];}return n - siz[rootedParent(u, v)];}int rootedLca(int a, int b, int c) {return lca(a, b) ^ lca(b, c) ^ lca(c, a);}
};struct DSU {std::vector<int> f, siz;DSU() {}DSU(int n) {init(n);}void init(int n) {f.resize(n);std::iota(f.begin(), f.end(), 0);siz.assign(n, 1);}int find(int x) {while (x != f[x]) {x = f[x] = f[f[x]];}return x;}bool same(int x, int y) {return find(x) == find(y);}bool merge(int x, int y) {x = find(x);y = find(y);if (x == y) {return false;}siz[x] += siz[y];f[y] = x;return true;}int size(int x) {return siz[find(x)];}
};
struct Diameter {int u;int v;int d;
};
Diameter merge(const Diameter& d1, const Diameter& d2, HLD& t) {Diameter res = d1;if (d2.d > res.d) {res = d2;}for (auto x : { d1.u, d1.v }) {for (auto y : { d2.u, d2.v }) {int d = t.dist(x, y);if (d > res.d) {res = { x, y, d };}}}return res;
}
signed main()
{ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);int T;cin >> T;while (T--){int n, q;cin >> n >> q;HLD t(n);for (int i = 1; i < n; i++) {int u, v;cin >> u >> v;u--, v--;t.addEdge(u, v);}t.work();vector<int>ans(q);DSU dsu(n + 1);vector<vector<int>>vec(q + 1);vector<int>col(n);for (int i = 0; i < q; i++) {int u, v;cin >> u >> v;u--, v--;int l = t.lca(u, v);for (auto x : { u,v }) {while (true) {int y = dsu.find(x);if (y == n || t.dep[y] < t.dep[l]) {break;}col[y] = 1;vec[i].push_back(y);dsu.merge(y ? t.parent[y] : n, y);}}}for (int i = 0; i < n; i++) {if (col[i] == 0) {vec[q].push_back(i);}}int res = 0;vector<Diameter>dia(n);for (int i = 0; i < n; i++) {dia[i] = { i,i,0 };}col.assign(n, 0);dsu.init(n);auto chk = [&](int x, int y) {if (col[x] != col[y]) {return;}x = dsu.find(x), y = dsu.find(y);dsu.merge(x, y);dia[x] = merge(dia[x], dia[y], t);res = max(res, dia[x].d);};auto chg = [&](int x, int c) {col[x] = c;for (auto y : t.adj[x]) {chk(x, y);}if (x) {chk(x, t.parent[x]);}};for (int i = 0; i < q; i++) {for (auto x : vec[i]) {chg(x, 1);}ans[i] = res;}col.assign(n, 1);dsu.init(n);for (int i = 0; i < n; i++) {dia[i] = { i, i, 0 };}res = 0;for (int i = q - 1; i >= 0; i--) {for (auto x : vec[i + 1]) {chg(x, 0);}ans[i] = std::max(ans[i], res);}for (int i = 0; i < q; i++) {std::cout << ans[i] + 1 << "\n";}}
}