# 点分治

P3806

## 2.不经过根的点对。

void findrt(int u, int fa) {
sz[u] = 1, son[u] = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v] || v == fa) continue;
findrt(v, u);
sz[u] += sz[v];
son[u] = max(son[u], sz[v]);
}
son[u] = max(son[u], S - sz[u]);
if (son[u] < son[rt]) rt = u;
}


void divide(int u) {
vis[u] = pd[0] = 1;
solve(u);
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v]) continue;
son[0] = n, S = sz[v], rt = 0;
findrt(v, u);
divide(rt);
}
}



void get_dis(int u, int fa) {
rev[++tot] = dis[u];
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (v == fa || vis[v]) continue;
dis[v] = dis[u] + ed[i].w;
get_dis(v, u);
}
}
int solve(int u) {
int c = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v]) continue;
tot = 0;
dis[v] = ed[i].w;
get_dis(v, u);
for (int j = 1; j <= tot; j++)
for (int k = 1; k <= m; k++)
if (que[k] >= rev[j])
ok[k] |= pd[que[k] - rev[j]];
for (int j = 1; j <= tot; j++)
if (rev[j] <= 10000000) q[++c] = rev[j], pd[rev[j]] = 1;
}
for (int i = 1; i <= c; i++) pd[q[i]] = 0;
}


P2634

ll solve(int u) {
ll cc = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v]) continue;
tot = 0;
dis[v] = ed[i].w;
get_dis(v, u);
for (int j = 1; j <= tot; j++) {
ll x = rev[j] % 3ll;
if (x == 0) cc += mp[0];
else cc += mp[3 - x];
}
for (int j = 1; j <= tot; j++)
mp[rev[j] % 3ll]++;
}
mp[0] = mp[1] = mp[2] = 0;
return cc;
}


P4149

void solve(int u) {
num[0] = dep[u] = 0;
int c = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v]) continue;
tot = 0;
dis[v] = ed[i].w;
get_dis(v, u);
for (int j = 1; j <= tot; j++)
if (k >= rev[j])
ans = min(ans, num[k - rev[j]] + cc[j]);
for (int j = 1; j <= tot; j++)
if (rev[j] <= k)
q[++c] = rev[j], num[rev[j]] = min(num[rev[j]], cc[j]);
}
for (int i = 1; i <= c; i++) num[q[i]] = inf;
}


CF161D Distance in Tree

P4178

void solve(int u) {
int c = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v]) continue;
tot = 0;
dis[v] = ed[i].w;
get_dis(v, u);
for (int j = 1; j <= tot; j++)
if (k >= rev[j])
ans += sum(k - rev[j] + 1);
for (int j = 1; j <= tot; j++)
if (k >= rev[j])
q[++c] = rev[j], add(rev[j] + 1, 1);
}
for (int i = 1; i <= c; i++) add(q[i] + 1, -1);


P2664

#include "bits/stdc++.h"

using namespace std;
int x = 0;
bool f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
if (f) return x;
return 0 - x;
}
#define SZ(x) ((int)x.size())
#define ll long long

const int maxn = 100000 + 10;
const ll inf = 1e18;
struct edge {
int u, v, nxt;
} ed[maxn << 1];
void add_e(int u, int v) {
}
int sz[maxn], son[maxn], vis[maxn], col[maxn], mx, rt, n, m, S;

void findrt(int u, int fa) {
sz[u] = 1, son[u] = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v] || v == fa) continue;
findrt(v, u);
sz[u] += sz[v];
son[u] = max(son[u], sz[v]);
}
son[u] = max(son[u], S - sz[u]);
if (son[u] < son[rt]) rt = u;
}
ll ans[maxn], c[maxn], mp[maxn], sum, num, tmp;

void dfs1(int u, int fa) {
mp[col[u]]++, sz[u] = 1;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v] || v == fa) continue;
dfs1(v, u);
sz[u] += sz[v];
}
if (mp[col[u]] == 1) {
sum += sz[u];
c[col[u]] += sz[u];
}
mp[col[u]]--;
}

void dfs(int u, int fa, int f) {
mp[col[u]]++;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (v == fa || vis[v]) continue;
dfs(v, u, f);
}
if (mp[col[u]] == 1) {
sum += sz[u] * f;
c[col[u]] += sz[u] * f;
}
mp[col[u]]--;
}

void dfs2(int u, int fa) {
mp[col[u]]++;
if (mp[col[u]] == 1) {
sum -= c[col[u]];
num++;
}
ans[u] += sum + num * tmp;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (v == fa || vis[v]) continue;
dfs2(v, u);
}
if (mp[col[u]] == 1) {
sum += c[col[u]];
num--;
}
mp[col[u]]--;
}

void clear(int u, int fa) {
c[col[u]] = mp[col[u]] = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (v == fa || vis[v]) continue;
clear(v, u);
}
}

void solve(int u) {
dfs1(u, 0);
ans[u] += sum;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v]) continue;
mp[col[u]]++, sum -= sz[v], c[col[u]] -= sz[v];
dfs(v, u, -1);
mp[col[u]]--;
tmp = sz[u] - sz[v];
dfs2(v, u);
mp[col[u]]++, sum += sz[v], c[col[u]] += sz[v];
dfs(v, u, 1);
mp[col[u]]--;
}
sum = num = 0;
clear(u, 0);

}

void divide(int u) {
vis[u] = 1;
solve(u);
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (vis[v]) continue;
S = sz[v];
son[rt = 0] = n;
findrt(v, 0);
divide(rt);
}
}

int main() {
for (int i = 1; i <= n; i++)
for (int i = 1, u, v; i < n; i++) {
}
S = son[rt = 0] = n;
findrt(1, 0);
divide(rt);
for (int i = 1; i <= n; i++) {
cout << ans[i] << endl;
}
return 0;
}


©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客