# CF 1039D You Are Given a Tree && CF1059E Split the Tree 的贪心解法

1039D 题意：

1059E 题意：

1039D

#include <bits/stdc++.h>

using namespace std;

const int N = 100000 + 5;
const int BLOCK = 100;

int n;
int f[N][2];
vector<int> node;
vector<int> g[N];
int fa[N];

void dfs(int u, int f = 1) {
for (auto v: g[u]) {
if (v != f) {
dfs(v, u);
}
}
node.push_back(u);
fa[u] = f;
}

int solve(int k) {
for (int i = 1; i <= n; i++) {
f[i][0] = f[i][1] = 0;
}
int ret = 0;
for (int u: node) {
if (f[u][0] + f[u][1] + 1 >= k) {
ret++;
} else {
if (f[fa[u]][0] < f[u][0] + 1) {
f[fa[u]][1] = f[fa[u]][0];
f[fa[u]][0] = f[u][0] + 1;
} else {
f[fa[u]][1] = max(f[fa[u]][1], f[u][0] + 1);
}
}
}
return ret;
}

int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d %d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1);
int x = N, k = 1;
while (x > BLOCK) {
x = solve(k++);
printf("%d\n", x);
}
for (int i = BLOCK; i >= 0; i--) {
if (solve(k) != i || k > n) {
continue;
}
int l = k, r = n + 1;
while (r - l > 1) {
int mid = (l + r) / 2;
if (solve(mid) == i) {
l = mid;
} else {
r = mid;
}
}
while (k <= l) {
printf("%d\n", i);
k++;
}
}
return 0;
}

### 1059E

#include <bits/stdc++.h>

using namespace std;

const int N = 100000 + 5;

int up[N];
int dep[N], path[N];
int fa[N][21];
int n, L;
int w[N];
long long S;
long long sumw[N];
vector<int> g[N];

void prepare(int u, int f = 0) {
dep[u] = dep[f] + 1;
sumw[u] = sumw[f] + w[u];
up[u] = u;
fa[u][0] = f;
for (int i = 1; i <= 20; i++) {
fa[u][i] = fa[fa[u][i-1]][i-1];
}
int lim = L-1;
for (int i = 20; i >= 0; i--) {
if (fa[up[u]][i] != 0 && (1 << i) <= lim && sumw[u] - sumw[fa[fa[up[u]][i]][0]] <= S) {
up[u] = fa[up[u]][i];
lim -= (1 << i);
}
}
for (int v: g[u]) {
prepare(v, u);
}
}

int solve(int u) {
int ret = 0, best = -1;
for (int v: g[u]) {
ret += solve(v);
if (path[v] != v) {
if (best == -1 || dep[path[v]] < dep[best]) {
best = path[v];
}
}
}
if (best == -1) {
ret++;
best = up[u];
}
path[u] = best;
return ret;
}

int main() {
scanf("%d %d %lld", &n, &L, &S);
for (int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
if (w[i] > S) {
printf("-1\n");
return 0;
}
}
for (int i = 2; i <= n; i++) {
int p;
scanf("%d", &p);
g[p].push_back(i);
}
prepare(1);
printf("%d\n", solve(1));
return 0;
}
posted @ 2018-10-11 20:15  蒟蒻lrz  阅读(...)  评论(...编辑  收藏