可持久化字典树0分求调
查看原帖
可持久化字典树0分求调
779997
like_tis楼主2024/11/2 18:36
#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
int n,q,tot1,tot2,vistime;
int a[100005],dfn[100005],rdfn[100005],siz[100005],fa[100005][18],trie1[100005*33][2],val1[100005*33],rt1[100005];
int trie2[100005*33][2],val2[100005*33],rt2[100005],dep[100005];
vector<int> g[100005];
void dfs(int u,int f){
    dfn[u]=++vistime;
    dep[u]=dep[f]+1;
    siz[u]=1;
    rdfn[vistime]=u;
    fa[u][0]=f;
    for(auto v:g[u])if(v!=f){
        dfs(v,u);
        siz[u]+=siz[v];
    }
}
void insert1(int u,int lst,int x){
    for(int i=(1<<30);i;i>>=1){
        val1[u]=val1[lst]+1;
        int A=bool(x&i);
        if(A==1){
            trie1[u][0]=trie1[lst][0];
            if(!trie1[u][1]) trie1[u][1]=++tot1;
            u=trie1[u][1];
            lst=trie1[lst][1];
        }
        else{
            trie1[u][1]=trie1[lst][1];
            if(!trie1[u][0]) trie1[u][0]=++tot1;
            u=trie1[u][0];
            lst=trie1[lst][0];
        }
    }
    val1[u]=val1[lst]+1;
}
int query1(int l,int r,int x){
    int ret=0;
    for(int i=(1<<30);i;i>>=1){
        int A=bool(x&i);
        if(val1[trie1[r][A^1]]-val1[trie1[l][A^1]]){
            l=trie1[l][A^1];
            r=trie1[r][A^1];
            ret+=i;
        }
        else{
            l=trie1[l][A];
            r=trie1[r][A];
        }
    }
    return ret;
}
void insert2(int u,int lst,int x){
    for(int i=(1<<30);i;i>>=1){
        val2[u]=val2[lst]+1;
        int A=bool(x&i);
        if(A==1){
            trie2[u][0]=trie2[lst][0];
            if(!trie2[u][1]) trie2[u][1]=++tot2;
            u=trie2[u][1];
            lst=trie2[lst][1];
        }
        else{
            trie2[u][1]=trie2[lst][1];
            if(!trie2[u][0]) trie2[u][0]=++tot2;
            u=trie2[u][0];
            lst=trie2[lst][0];
        }
    }
    val2[u]=val2[lst]+1;
}
int query2(int l,int r,int x){
    int ret=0;
    for(int i=(1<<30);i;i>>=1){
        int A=bool(x&i);
        if(val2[trie2[r][A^1]]-val2[trie2[l][A^1]]){
            l=trie2[l][A^1];
            r=trie2[r][A^1];
            ret+=i;
        }
        else{
            l=trie2[l][A];
            r=trie2[r][A];
        }
    }
    return ret;
}
int lca(int u,int v){
    if(dep[u]<dep[v]) swap(u,v);
    for(int i=17;i>=0;i--){
        if(dep[fa[u][i]]>=v){
            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(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,0);
    for(int i=1;i<=n;i++){
        rt1[i]=++tot1;
        insert1(rt1[i],rt1[i-1],a[rdfn[i]]);
        rt2[i]=++tot2;
        insert2(rt2[i],rt2[fa[i][0]],a[i]);
    }
    for(int k=1;k<=17;k++){
        for(int i=1;i<=n;i++){
            fa[i][k]=fa[fa[i][k-1]][k-1];
        }
    }
    while(q--){
        int op,u,v,x;
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d",&u,&x);
            printf("%d\n",query1(rt1[dfn[u]-1],rt1[dfn[u]+siz[u]-1],x));
        }
        else{
            scanf("%d%d%d",&u,&v,&x);
            int LCA=lca(u,v);
            printf("%d\n",max(query2(rt2[fa[LCA][0]],rt2[u],x),query2(rt2[fa[LCA][0]],rt2[v],x)));
        }
    }
    return 0;
}
2024/11/2 18:36
加载中...