2021牛客多校3
题号 | 标题 | 团队的状态 |
---|---|---|
A | Guess and lies | 通过 |
B | Black and white | 通过 |
C | Minimum grid | 通过 |
D | Count | 通过 |
E | Math | 通过 |
F | 24dian | 通过 |
G | Yu Ling(Ling YueZheng) and Colorful Tree | 通过 |
H | Ling Qiu, Luna and Triple Backpack | 未通过 |
I | Kuriyama Mirai and Exclusive Or | 通过 |
J | Counting Triangles | 通过 |
Guess and lies
Black and white
Minimum grid
Count
Math
24dian
Yu Ling(Ling YueZheng) and Colorful Tree
一棵 \(n\) 个点的树,1 是根。\(q\) 次操作:
0 u x
令 \(\mathrm{color}_u=x\)。1 u l r x
询问离 \(u\) 的最近祖先 \(v\) 满足 \(l \leq \mathrm{color}_v \leq r, x \mid \mathrm{color}_v\)。\(n, q \leq 1.1\times 10^5, 1 \leq x \leq n\),染色操作的点和颜色都互不相同。
跑一遍 dfs 序,祖先的限制转化为 \(\mathrm{in}_v \leq \mathrm{in}_u \leq \mathrm{out}_v\)。
离线,将染色 \(x\) 和询问颜色 \(x\) 的操作都存下来,分别处理。
对于颜色 \(x\) 的询问,将 \(l, r\) 离散化,然后枚举 \(x\) 的倍数去掉 \(x \mid \mathrm{color}_v\) 的限制。
剩下来是一个三维偏序问题: \[ \begin{cases} t_v < t_u, \\ \mathrm{in}_v \leq \mathrm{in}_u \leq \mathrm{out}_v,\\ l \leq \mathrm{color}_v \leq r \end{cases} \] 可以树套树解决。
对于离散化后的颜色区间建立线段树,将询问和修改都挂在线段树上,去掉第三维。
然后对线段树的每个节点做一个二维偏序即可。
复杂度 \(O(n \log^3 n)\)。
// Author: HolyK
// Created: Sun Jul 25 14:59:29 2021
#include <bits/stdc++.h>
#define dbg(a...) fprintf(stderr, a)
template <class T, class U>
inline bool smin(T &x, const U &y) {
return y < x ? x = y, 1 : 0;
}
template <class T, class U>
inline bool smax(T &x, const U &y) {
return x < y ? x = y, 1 : 0;
}
using LL = long long;
using PII = std::pair<int, int>;
inline char gc() {
static constexpr int BufferSize = 1 << 22 | 5;
static char buf[BufferSize], *p, *q;
static std::streambuf *i = std::cin.rdbuf();
return p == q ? p = buf, q = p + i->sgetn(p, BufferSize), p == q ? EOF : *p++ : *p++;
}
struct Reader {
template <class T>
&operator>>(T &w) {
Reader char c, p = 0;
for (; !std::isdigit(c = gc());) if (c == '-') p = 1;
for (w = c & 15; std::isdigit(c = gc()); w = w * 10 + (c & 15)) ;
if (p) w = -w;
return *this;
}
} cin;
constexpr int N(1.1e5 + 5);
int n, m;
std::vector<PII> g[N];
[N];
LL dint in[N], out[N], cnt;
void dfs(int x, int p) {
[x] = cnt++;
infor (auto [y, z] : g[x]) {
if (y == p) continue;
[y] = d[x] + z;
d(y, x);
dfs}
[x] = cnt;
out}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
>> n >> m;
cin for (int i = 1, x, y, z; i < n; i++) {
>> x >> y >> z;
cin --, y--;
x[x].emplace_back(y, z);
g[y].emplace_back(x, z);
g}
[0] = 1;
d(0, -1);
dfsstd::vector<PII> a(n + 1, PII(-1, -1));
using Qry = std::array<int, 4>;
std::vector<std::vector<Qry>> q(n + 1);
std::vector<LL> ans(m);
for (int i = 0; i < m; i++) {
int opt, u, l, r, x;
>> opt >> u;
cin --;
uif (opt == 0) {
>> x;
cin assert(a[x].first == -1);
[x] = {u, i};
a[i] = -1;
ans} else {
>> l >> r >> x;
cin = (l + x - 1) / x * x;
l = (r + x) / x * x;
r [i] = 1e18;
ansif (l < r) {
[x].push_back({u, l, r, i});
q}
}
}
std::vector<int> p;
std::vector<Qry> b;
for (int x = 1; x <= n; x++) {
if (q[x].empty()) continue;
.clear();
pfor (auto [u, l, r, id] : q[x]) {
.push_back(l);
p.push_back(r);
p}
std::sort(p.begin(), p.end());
.resize(std::unique(p.begin(), p.end()) - p.begin());
p.clear();
b#define low(x) int(std::lower_bound(p.begin(), p.end(), x) - p.begin())
#define upp(x) int(std::upper_bound(p.begin(), p.end(), x) - p.begin())
for (int y = p[0]; y < p.back(); y += x) {
if (a[y].first == -1) continue;
auto [u, id] = a[y];
.push_back({id, u, upp(y) - 1, -1});
b}
for (auto [u, l, r, id] : q[x]) {
.push_back({id, u, low(l), low(r)});
b}
std::sort(b.begin(), b.end());
int s = 1 << std::__lg(p.size() * 2 - 1);
std::vector<int> len(2 * s);
for (auto [id, u, l, r] : b) {
if (r == -1) {
for (l += s; l; l >>= 1) {
[l]++;
len}
} else {
for (l += s, r += s; l < r; l >>= 1, r >>= 1) {
if (l & 1) {
[l++]++;
len}
if (r & 1) {
[--r]++;
len}
}
}
}
std::vector<std::vector<PII>> t(2 * s);
for (int i = 1; i < 2 * s; i++) t.reserve(len[i]);
for (auto [id, u, l, r] : b) {
if (r == -1) {
for (l += s; l; l >>= 1) {
[l].emplace_back(id, u);
t}
} else {
for (l += s, r += s; l < r; l >>= 1, r >>= 1) {
if (l & 1) {
[l++].emplace_back(id, u);
t}
if (r & 1) {
[--r].emplace_back(id, u);
t}
}
}
}
for (auto &v : t) {
if (v.empty()) continue;
.clear();
pfor (auto [id, u] : v) {
if (~ans[id]) p.push_back(in[u]);
}
std::sort(p.begin(), p.end());
.resize(std::unique(p.begin(), p.end()) - p.begin());
pint s = 1 << std::__lg(p.size() * 2 - 1);
std::vector<LL> max(2 * s);
for (auto [id, u] : v) {
if (ans[id] == -1) {
for (int l = s + low(in[u]), r = s + low(out[u]); l < r; l >>= 1, r >>= 1) {
if (l & 1) smax(max[l++], d[u]);
if (r & 1) smax(max[--r], d[u]);
}
} else {
= 0;
LL m for (int l = s + low(in[u]); l; l >>= 1) {
(m, max[l]);
smax}
if (m) smin(ans[id], d[u] - m);
}
}
}
}
for (int i = 0; i < m; i++) {
if (~ans[i]) {
if (ans[i] < 1e18) {
std::cout << ans[i] << "\n";
} else {
std::cout << "Impossible!\n";
}
}
}
return 0;
}
Ling Qiu, Luna and Triple Backpack
Kuriyama Mirai and Exclusive Or
Counting Triangles
最后修改于 2021-08-13