luoguP3359 改造异或树 线段树合并

Posted reverymoon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP3359 改造异或树 线段树合并相关的知识,希望对你有一定的参考价值。

技术分享图片

删边转化为加边

然后每次用线段树合并就行.....

确确实实很简单

然而为什么线段树合并跑不过$splay$的启发式合并,常数稍大了点...

复杂度$O(n log n)$

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
namespace remoon {
    #define ri register int
    #define ll long long
    #define tpr template <typename ra>
    #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++)
    #define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --)    
    #define gc getchar
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > 9 || c < 0) { if(c == -) w = -1; c = gc(); }
        while(c >= 0 && c <= 9) p = p * 10 + c - 0, c = gc();
        return p * w;
    }
    int wr[50], rw;
    #define pc(iw) putchar(iw)
    tpr inline void write(ra o, char c = 
) {
        if(!o) pc(0);
        if(o < 0) o = -o, pc(-);
        while(o) wr[++ rw] = o % 10, o /= 10;
        while(rw) pc(wr[rw --] + 0);
        pc(c);
    }
}
using namespace std;
using namespace remoon;#define sid 200050
#define pid 5000500

ll ans;
ll sum[sid];
int n, id, cnp;
int x[sid], y[sid], p[sid];
int cap[sid], nxt[sid], node[sid], val[sid], s[sid];
int fa[sid], rt[sid], ls[pid], rs[pid], sz[pid];

inline void addedge(int u, int v, int w) {
    nxt[++ cnp] = cap[u]; cap[u] = cnp;
    node[cnp] = v; val[cnp] = w;
    nxt[++ cnp] = cap[v]; cap[v] = cnp;
    node[cnp] = u; val[cnp] = w;
}

inline int find(int o) {
    if(fa[o] == o) return o;
    return fa[o] = find(fa[o]);
}

inline void insert(int &now, int l, int r, int v) {
    now = ++ id; sz[now] = 1;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(v <= mid) insert(ls[now], l, mid, v);
    else insert(rs[now], mid + 1, r, v);
}

inline int merge(int x, int y, int l = 0, int r = 1 << 30) {
    if(!x || !y) return x + y;
    if(l == r) ans += 1ll * sz[x] * sz[y];
    int mid = (l + r) >> 1;
    ls[x] = merge(ls[x], ls[y], l, mid);
    rs[x] = merge(rs[x], rs[y], mid + 1, r);
    sz[x] += sz[y];
    return x;
}

#define cur node[i]
inline void dfs(int o, int f) {
    insert(rt[o], 0, 1 << 30, s[o]);
    for(int i = cap[o]; i; i = nxt[i])
    if(cur != f) s[cur] = s[o] ^ val[i], dfs(cur, o);
}

int main() {
    n = read();
    rep(i, 1, n - 1) {
        x[i] = read(); y[i] = read(); 
        int w = read(); addedge(x[i], y[i], w);
    }
    rep(i, 1, n) fa[i] = i;
    rep(i, 1, n - 1) p[i] = read();
    dfs(1, 0);
    drep(i, n - 1, 1) {
        int u = find(x[p[i]]), v = find(y[p[i]]);
        fa[v] = u; merge(rt[u], rt[v]);
        sum[i] = ans;
    }
    rep(i, 1, n) write(sum[i]);
    return 0;
}

 

以上是关于luoguP3359 改造异或树 线段树合并的主要内容,如果未能解决你的问题,请参考以下文章

luoguP5161 WD与数列 后缀自动机+线段树合并+启发式合并

bzoj2333 & luoguP3273棘手的操作(线段树合并)

luoguP4755 Beautiful Pair 笛卡尔树+线段树合并+启发式合并

luoguP4755 Beautiful Pair 笛卡尔树+线段树合并+启发式合并

HDU 4825 Trie树 异或树!

EOJ 2021.10 E.异或树