目录
H. Genshin Impact Startup Forbidden III
K. Points on the Number Axis B
估计还会补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
大致思路是先找到白变黑的顺序将其放再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";
}
}
}