洛谷P4592 [TJOI2018]异或 【可持久化trie树】

题目链接

BZOJ4592

题解

可持久化trie树裸题

写完就A了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 100005,B = 30,maxm = 5000005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    return out * flag;
}
int bin[50];
struct Trie{
    int ch[maxm][2],sum[maxm],rt[maxn],cnt;
    int ins(int pre,int x){
        int tmp,u;
        tmp = u = ++cnt;
        for (int i = B; i >= 0; i--){
            ch[u][0] = ch[pre][0];
            ch[u][1] = ch[pre][1];
            sum[u] = sum[pre] + 1;
            int t = x & bin[i]; t >>= i;
            pre = ch[pre][t];
            u = ch[u][t] = ++cnt;
        }
        sum[u] = sum[pre] + 1;
        return tmp;
    }
    int query(int pre,int u,int x,int dep){
        if (dep < 0) return 0;
        int t = x & bin[dep]; t >>= dep;
        if (sum[ch[u][t ^ 1]] - sum[ch[pre][t ^ 1]])
            return bin[dep] + query(ch[pre][t ^ 1],ch[u][t ^ 1],x,dep - 1);
        return query(ch[pre][t],ch[u][t],x,dep - 1);
    }
    int Query(int a,int b,int c,int d,int x,int dep){
        if (dep < 0) return 0;
        int t = x & bin[dep]; t >>= dep;
        if (sum[ch[a][t ^ 1]] + sum[ch[b][t ^ 1]] - sum[ch[c][t ^ 1]] - sum[ch[d][t ^ 1]])
            return bin[dep] + Query(ch[a][t ^ 1],ch[b][t ^ 1],ch[c][t ^ 1],ch[d][t ^ 1],x,dep - 1);
        return Query(ch[a][t],ch[b][t],ch[c][t],ch[d][t],x,dep - 1);
    }
}T1,T2;
int n,Q,val[maxn];
int h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxn << 1];
inline void build(int u,int v){
    ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
int dfn[maxn],fa[maxn][18],at[maxn],siz[maxn],dep[maxn],cnt;
void dfs(int u){
    dfn[u] = ++cnt; at[cnt] = u; siz[u] = 1;
    T1.rt[u] = T1.ins(T1.rt[fa[u][0]],val[u]);
    REP(i,17) fa[u][i] =fa[fa[u][i - 1]][i - 1];
    Redge(u) if ((to = ed[k].to) != fa[u][0]){
        fa[to][0] = u; dep[to] = dep[u] + 1; dfs(to);
        siz[u] += siz[to];
    }
}
int lca(int u,int v){
    if (dep[u] < dep[v]) swap(u,v);
    for (int i = 0,d = dep[u] - dep[v]; (1 << i) <= d; i++)
        if (d & (1 << i)) u = fa[u][i];
    if (u == v) return u;
    for (int i = 17; i >= 0; i--)
        if (fa[u][i] != fa[v][i]){
            u = fa[u][i];
            v = fa[v][i];
        }
    return fa[u][0];
}
int main(){
    bin[0] = 1; REP(i,30) bin[i] = bin[i - 1] << 1;
    n = read(); Q = read();
    REP(i,n) val[i] = read();
    for (int i = 1; i < n; i++) build(read(),read());
    dfs(1);
    for (int i = 1; i <= n; i++)
        T2.rt[i] = T2.ins(T2.rt[i - 1],val[at[i]]);
    int opt,x,y,z,o;
    while (Q--){
        opt = read(); x = read(); y = read();
        if (opt & 1){
            printf("%d\n",T2.query(T2.rt[dfn[x] - 1],T2.rt[dfn[x] + siz[x] - 1],y,B));
        }
        else {
            z = read(); o = lca(x,y);
            printf("%d\n",T1.Query(T1.rt[x],T1.rt[y],T1.rt[o],T1.rt[fa[o][0]],z,B));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mychael/p/9049815.html