[TJOI2018]异或【可持久化Trie+树剖】

[TJOI2018]异或
把树剖套的线段树换成可持久化\(Trie\)树就结束了

int val[Maxm], ch[Maxm][2], T_cnt;
void ins(int i, int o, int p, int x, int now){
    if(now < 0) {val[o]=i; return;} 
    int k=x>>now&1; if(ch[p][k^1]) ch[o][k^1]=ch[p][k^1]; ch[o][k]=++T_cnt;
    ins(i, ch[o][k], ch[p][k], x, now-1); val[o]=max(val[ch[o][0]], val[ch[o][1]]);
}

int fa[Maxn], top[Maxn], dfn[Maxn], rnk[Maxn], cnt, sz[Maxn], hson[Maxn], dep[Maxn];
void dfs1(int u){ sz[u]=1;
    for(int i=head[u], v; i; i=nxt[i])if((v=to[i]) !=fa[u]){
        fa[v]=u, dep[v]=dep[u]+1; dfs1(v); 
        sz[u]+=sz[v]; if(sz[v] > sz[hson[u]]) hson[u]=v;
    }
}
void dfs2(int u, int anc){
    top[u]=anc; dfn[u]=++cnt; rnk[cnt]=u; if(hson[u]) dfs2(hson[u], anc); else return ;
    for(int i=head[u], v; i; i=nxt[i]) if((v=to[i]) != fa[u] && v != hson[u]) dfs2(v, v);
}
int query(int L, int o, int x, int now){
    if(now < 0) return v[rnk[val[o]]]^x; int k=x>>now&1;
    if(val[ch[o][k^1]] >= L) return query(L, ch[o][k^1], x, now-1);
    return query(L, ch[o][k], x, now-1);
}

void cal(int u, int v, int z){
    int tu=top[u], tv=top[v], ans=0;
    while(tu != tv){
        if(dep[tu] < dep[tv]) swap(u, v), swap(tu, tv);
        ans=max(ans, query(dfn[tu], rt[dfn[u]], z, 30));
        u=fa[tu], tu=top[u];
    }
    if(dep[u] < dep[v]) swap(u, v); ans=max(ans, query(dfn[v], rt[dfn[u]], z, 30));
    printf("%d\n", ans);
}
void solve(){
    n=read(), q=read();
    for(int i=1; i <= n; i++) v[i]=read();
    for(int i=1, u, v; i < n; i++) u=read(), v=read(), add(u, v), add(v, u);
    dfs1(1); dfs2(1, 1); 
    for(int i=1; i <= n; i++) rt[i]=++T_cnt, ins(i, rt[i], rt[i-1], v[rnk[i]], 30);
    while(q--){
        int cmd=read(), x=read(), y=read(), z;
        if(cmd == 1) printf("%d\n", query(dfn[x], rt[dfn[x]+sz[x]-1], y, 30));
        else z=read(), cal(x, y, z);
    }
}

转载于:https://www.cnblogs.com/zerolt/p/9297012.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值