萌新刚学OI,求助点分治
  • 板块P4178 Tree
  • 楼主_Emiria_
  • 当前回复1
  • 已保存回复1
  • 发布时间2021/11/11 19:30
  • 上次更新2023/11/4 00:52:24
查看原帖
萌新刚学OI,求助点分治
287868
_Emiria_楼主2021/11/11 19:30

rt,后四个点WA

#include <cstdio>
#include <iostream>

#define int long long
#define maxn 2000005

using std::max;

inline char nc () {  
    static char buf[1 << 21], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread (buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read () {
    register int x(0), f(1); char ch = nc ();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -f; ch = nc ();}
    while (ch >= '0' && ch <= '9') {x = x*10 + ch-'0'; ch = nc ();}
    return x * f;
}

template <class I>
class fhq{
    private:
        int Root, cnt;

        struct T{
            int lson, rson, key, rnd, sz;
        }t[1000000];

    public:
        inline int make(int k){
            int root = ++cnt;
            t[root].lson = t[root].rson = 0;
            t[root].key = k;
            t[root].rnd = rand();
            t[root].sz = 1;
            return root;
        }

        inline void update(int root){
            t[root].sz = t[t[root].lson].sz + t[t[root].rson].sz + 1;
        }

        inline void split(int root, int k, int &x, int &y){
            if(!root){
                x = y = 0;
                return;
            }
            if(t[root].key <= k){
                x = root;
                split(t[root].rson, k, t[root].rson, y);
            }
            else{
                y = root;
                split(t[root].lson, k, x, t[root].lson);
            }
            update(root);
        }

        inline int merge(int x, int y){
            if(!x | !y){
                return x | y;
            }
            if(t[x].rnd < t[y].rnd){
                t[x].rson = merge(t[x].rson, y);
                update(x);
                return x;
            }
            else{
                t[y].lson = merge(x, t[y].lson);
                update(y);
                return y;
            }
        }

        inline void add(int k){
            int x, y;
            split(Root, k - 1, x, y);
            Root = merge(merge(x, make(k)), y);
        }

        inline void del(int k){
            int x, y, z;
            split(Root, k, x, z);
            split(x, k - 1, x, y);
            if(y) y = merge(t[y].lson, t[y].rson);
            Root = merge(merge(x, y), z);
        }

        inline int lower(int k){
            int x, y, ans;
            split(Root, k - 1, x, y);
            ans = t[x].sz;
            Root = merge(x, y);
            return ans;
        }
};

fhq < int > t;

struct Edge{
    int start, end, val, nxt;
}edge[maxn << 1];

int cnt_edge, head[maxn];

inline void add_edge(int u, int v, int w){
    edge[++cnt_edge] = (Edge){u, v, w, head[u]};
    head[u] = cnt_edge;
}

int rem[maxn], sz[maxn], ans;
int n, m, rt, tot, maxp[maxn];
int top, dis[40000005], que[maxn];

bool have[40000005], vis[maxn];

int u, v, w, q;

inline void get_dis(int u, int f){
    rem[++rem[0]] = dis[u];
    for(int i = head[u]; i; i = edge[i].nxt){
        int v = edge[i].end;
        if(v == f || vis[v]) continue;
        dis[v] = dis[u] + edge[i].val;
        get_dis(v, u);
    }
}

inline void get_rt(int u, int f){
    sz[u] = 1, maxp[u] = 0;
    for(int i = head[u]; i; i = edge[i].nxt){
        int v = edge[i].end;
        if(v == f || vis[v]) continue;
        get_rt(v, u);
        sz[u] += sz[v];
        maxp[u] = max(maxp[u], sz[v]);
    }
    maxp[u] = max(maxp[u], tot - sz[u]);
    if(maxp[u] < maxp[rt]) rt = u;
}

inline void work(int u){
    for(int i = head[u]; i; i = edge[i].nxt){
        int v = edge[i].end;
        if(vis[v]) continue;
        rem[0] = 0, dis[v] = edge[i].val;
        get_dis(v, u);
        for(int j = rem[0]; j; j--){
            if(q >= rem[j]){
                ans += t.lower(q - rem[j]);
            }
        }
        for(int j = rem[0]; j; j--){
            t.add(rem[j]);
            que[++top] = rem[j];
        }
    }
   while(top){
        t.del(que[top--]);
    }
    t.del(0);
}

inline void divide(int u){
    vis[u] = 1;
    t.add(0);
    work(u);
    for(int i = head[u]; i; i = edge[i].nxt){
        int v = edge[i].end;
        if(vis[v]) continue;
        tot = maxp[rt = 0] = sz[v];
        get_rt(v, 0);
        get_rt(rt, 0);
        divide(rt);
    }
}

signed main(){
    n = read();
    for(int i = 1; i < n; i++){
        u = read(); v = read(); w = read();
        add_edge(u, v, w);
        add_edge(v, u, w);
    }
    q = read();
    maxp[rt] = tot = maxn;
    get_rt(1, 0);
    get_rt(rt, 0);
    divide(rt);
    printf("%lld\n", ans);
    return 0;
}
2021/11/11 19:30
加载中...