点分治

P4178 Tree

点击查看代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
int n, m, p[N], q[N], h[N], e[N << 1], ne[N << 1], idx, w[N << 1], qt;
bool st[N];
void add(int u, int v, int W){
    e[++idx] = v, ne[idx] = h[u], h[u] = idx, w[idx] = W;
}
int getsz(int u, int fa){
    if (st[u]) return 0;
    int res = 1;
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        if (v == fa) continue;
        res += getsz(v, u);
    }
    return res;
}
int getwc(int u, int fa, int tot, int &wc){
    if (st[u]) return 0;
    int s = 1, mx = 0;
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        if (v == fa) continue;
        int t = getwc(v, u, tot, wc);
        mx = max(mx, t), s += t;
    }
    mx = max(mx, tot - s);
    if (mx <= tot / 2) wc = u;
    return s;
}
void getd(int u, int fa, int d){
    if (st[u]) return;
    q[++qt] = d;
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        if (v == fa) continue;
        getd(v, u, d + w[i]);
    }
}
int calc(int a[], int k){
    sort(a + 1, a + k + 1);
    int res = 0;
    for (int i = k, j = 0; i >= 1; i--){
        while (j + 1 < i && a[j + 1] + a[i] <= m) j++;
        j = min(j, i - 1), res += j;
    }
    return res;
}
int dfs(int u){
    if (st[u]) return 0;
    int res = 0, pt = 0;
    getwc(u, -1, getsz(u, -1), u);
    st[u] = 1;
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        qt = 0, getd(v, -1, w[i]);
        res -= calc(q, qt);
        for (int k = 1; k <= qt; k++){
            if (q[k] <= m) res++;
            p[++pt] = q[k];
        }
    }
    res += calc(p, pt);
    for (int i = h[u]; i; i = ne[i]) res += dfs(e[i]);
    return res;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    while (cin >> n >> m, n || m){
        memset(h, 0, sizeof(h));
        memset(st, 0, sizeof(st)), idx = 0;
        for (int i = 1, u, v, w; i < n; i++)
            cin >> u >> v >> w, add(u, v, w), add(v, u, w);
        cout << dfs(0) << endl;
    }
    return 0;
}

P4149 [IOI 2011] Race

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
const int N = 200005, INF = 0x3f3f3f3f;
int n, m, h[N], e[N << 1], ne[N << 1], idx, w[N << 1], qt, f[1000005], ans = INF;
pair<int, int> p[N], q[N];
bool st[N];
void add(int u, int v, int W){
    e[++idx] = v, ne[idx] = h[u], h[u] = idx, w[idx] = W;
}
int getsz(int u, int fa){
    if (st[u]) return 0;
    int res = 1;
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        if (v == fa) continue;
        res += getsz(v, u);
    }
    return res;
}
int getwc(int u, int fa, int tot, int &wc){
    if (st[u]) return 0;
    int s = 1, mx = 0;
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        if (v == fa) continue;
        int t = getwc(v, u, tot, wc);
        mx = max(mx, t), s += t;
    }
    mx = max(mx, tot - s);
    if (mx <= tot / 2) wc = u;
    return s;
}
void getd(int u, int fa, int d,int cnt){
    if (st[u] || d > m) return;
    q[++qt] = {d, cnt};
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        if (v == fa) continue;
        getd(v, u, d + w[i], cnt + 1);
    }
}
void dfs(int u){
    if (st[u]) return;
    int pt = 0;
    getwc(u, -1, getsz(u, -1), u);
    st[u] = 1;
    for (int i = h[u]; i; i = ne[i]){
        int v = e[i];
        qt = 0, getd(v, -1, w[i], 1);
        for (int k = 1; k <= qt; k++){
            auto &t = q[k];
            if (t.fi == m) ans = min(ans, t.se);
            ans = min(ans, f[m - t.fi] + t.se);
            p[++pt] = t;
        }
        for (int k = 1; k <= qt; k++){
            auto& t = q[k];
            f[t.fi] = min(f[t.fi], t.se);
        }
    }
    for (int i = 1; i <= pt;i++) f[p[i].fi] = INF;
    for (int i = h[u]; i; i = ne[i]) dfs(e[i]);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    for (int i = 1, u, v, w; i < n; i++)
        cin >> u >> v >> w, add(u, v, w), add(v, u, w);
    memset(f, 0x3f, sizeof(f));
    dfs(0);
    cout << (ans == INF ? -1 : ans) << endl;
    return 0;
}

P3806 【模板】点分治

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 10005, M = N * 2;
int h[N], e[M], ne[M], w[M], idx, n, q, ask[105];
int rt, sz[N], mx[N], sum, d[N], dis[N], cnt;
bool vis[N], ans[N], t[10000005];
vector<int> vec;
void add(int u,int v,int W){
    e[++idx] = v, w[idx] = W, ne[idx] = h[u], h[u] = idx;
}
void get_rt(int u,int fa){
    sz[u] = 1, mx[u] = 0;
    for (int i = h[u]; i;i=ne[i]){
        int v = e[i];
        if (v == fa || vis[v]) continue;
        get_rt(v, u);
        sz[u] += sz[v], mx[u] = max(mx[u], sz[v]);
    }
    mx[u] = max(mx[u], sum - sz[u]);
    rt = (mx[rt] < mx[u] ? rt : u);
}
void get_dis(int u,int fa){
    d[++cnt] = dis[u];
    for (int i = h[u]; i;i=ne[i]){
        int v = e[i];
        if(v==fa||vis[v]) continue;
        dis[v] = dis[u] + w[i];
        get_dis(v, u);
    }
}
void calc(int u){
    vec.clear(), t[0] = 1;
    for (int i = h[u]; i;i=ne[i]){
        int v = e[i];
        if(vis[v]) continue;
        dis[v] = w[i], cnt = 0;
        get_dis(v, 0);
        for (int j = 1; j <= cnt; j++)
            for (int k = 1; k <= q; k++){
                if (ask[k] < d[j]) continue;
                ans[k] |= t[ask[k] - d[j]];
            }
        for (int j = 1; j <= cnt;j++){
            if (d[j] > 1e7) continue;
            if(!t[d[j]]) t[d[j]] = 1, vec.push_back(d[j]);
        }
    }
    for (int i = 0; i < vec.size();i++) t[vec[i]] = 0;
}
void dfs(int u){
    vis[u] = 1, calc(u);
    for (int i = h[u]; i;i=ne[i]){
        int v = e[i];
        if(vis[v]) continue;
        mx[rt = 0] = sum = sz[v];
        get_rt(v, 0), dfs(rt);
    }
}
int main(){
    cin >> n >> q;
    for (int i = 1, x, y, z; i < n; i++)
        cin >> x >> y >> z, add(x, y, z), add(y, x, z);
    for (int i = 1; i <= q;i++) cin >> ask[i];
    mx[rt] = sum = n;
    get_rt(1, 0), dfs(rt);
    for (int i = 1; i <= q;i++) cout << (ans[i] ? "AYE" : "NAY") << endl;
}
posted @ 2026-02-02 09:47  Star_F  阅读(1)  评论(0)    收藏  举报