day-10
杭电多校二
二进制枚举 https://acm.hdu.edu.cn/showproblem.php?pid=6971
核心问题: 更新数组a[],使 a[i] = max({a[j}),其中,i|k=j 即j能完全包含i
一般情况下 n^2枚举
可以按0的个数建个图比如
111
110 101 011
100 010 001
000
可以枚举|1的位置,如果i在k位上没有1,就能更新a[i] = max(a[i],a[i|(1<<k)])
其实理解了看代码更清晰
int m = 1;
while (m < n) m <<= 1;
for (int k = 1; (1 << k) < m; k++)
for (int i = m - 1; i >= 1; i--)
if (!(i & (1 << k)))//i能完全包含k
a[i] = max(a[i], a[i | (1 << k)]);
树链剖分 + 线段树
const int maxn = 1e5 + 7;
int n, t, u, v, m;
int cnt;
int dep[maxn], fa[maxn], siz[maxn], son[maxn], top[maxn], dfn[maxn], rnk[maxn];
vector<int> mp[maxn];
void dfs1(int o) {
son[o] = -1;
siz[o] = 1;
for (auto x:mp[o]) {
if (dep[x])
continue;
dep[x] = dep[o] + 1;
fa[x] = o;
dfs1(x);
siz[o] += siz[x];
if (son[o] == -1 || siz[x] > siz[son[o]])
son[o] = x;
}
}
void dfs2(int o, int tp) {
if (cnt >= n)
return;
top[o] = tp;
dfn[o] = ++cnt;
rnk[cnt] = o;
if (son[o] == -1)
return;
dfs2(son[o], tp);
for (auto x:mp[o])
if (x != son[o] && x != fa[o]) dfs2(x, x);
}
void solve() {
cin >> n;
for (int i = 1; i < n; i++)
cin >> u >> v, mp[u].push_back(v), mp[v].push_back(u);
dep[1] = 1; //记得加上
dfs1(1);
dfs2(1, 1);
return;
}
我看见 你