【题解】hdu4757 【TJOI2018】异或

题目链接

题目大意:有一颗树,有点权,每次询问:一条路径\(x->y\)中与\(z\)异或的最大值,或是以\(x\)为根的子树中与\(y\)异或的最大值。

树剖……还是算了。

观察到,子树的\(dfn\)序是连续的一段区间。于是我们可以预处理\(dfs\)序来解决这个问题。

第二问,我们可以求两点的最近公共祖先,做一个树上差分来实现。

维护两颗可持久化\(Trie.\)一个维护\(dfs\)序,一个维护\(x->root\).

当然\(HDU\)的那个题是没有第一个操作的,但是是多组询问。

\(HDU:\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
int n,m,siz[MAXN],dfn[MAXN],f[MAXN][25];
int dep[MAXN],head[MAXN<<1],tot,dfstime;
int pre[MAXN],a[MAXN];
struct edge{
    int nxt,to;
}e[MAXN<<1];
inline void add(int x,int y){
    e[++tot].to=y;
    e[tot].nxt=head[x];
    head[x]=tot;
}
struct Trie{
    int son[MAXN<<5][2],ct[MAXN<<5],root[MAXN],cnt=1;
    void Insert(int &rt,int x,int T){
        ct[++cnt]=ct[rt]+1;
        son[cnt][0]=son[rt][0];
        son[cnt][1]=son[rt][1];
        rt=cnt;
        if(T==-1)return;
        bool y=(x>>T)&1;
        Insert(son[rt][y],x,T-1);
    }
    void Ins(int pre,int rt,int x){
        root[rt]=root[pre];
        Insert(root[rt],x,30);
    }
    int Q(int i,int j,int x,int T){
        if(T==-1)return 0;
        int y=(x>>T)&1;
        if(ct[son[j][1^y]]>ct[son[i][1^y]])return ((1<<T)+Q(son[i][1^y],son[j][1^y],x,T-1));
        return Q(son[i][y],son[j][y],x,T-1);
    } 
    int QT(int i,int j,int lc,int flc,int x,int T){
        if(T==-1)return 0;
        int y=(x>>T)&1;
        if(ct[son[i][1^y]]+ct[son[j][1^y]]>ct[son[lc][1^y]]+ct[son[flc][1^y]])return ((1<<T)+QT(son[i][1^y],son[j][1^y],son[lc][1^y],son[flc][1^y],x,T-1));
        else return QT(son[i][y],son[j][y],son[lc][y],son[flc][y],x,T-1);
    }
    int query(int i,int j,int x){
        return Q(root[i-1],root[j],x,30);
    }
    int UQT(int i,int j,int lc,int flc,int x){
        return QT(root[i],root[j],root[lc],root[flc],x,30);
    }
    void clear(){
        cnt=1;
        memset(root,0,sizeof(root));
        memset(ct,0,sizeof(ct));
        memset(son,0,sizeof(son));
    }
}tr1;
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;siz[u]=1;
    pre[dfn[u]=++dfstime]=u;
    f[u][0]=fa;
    for(int i=1;i<=22;++i)f[u][i]=f[f[u][i-1]][i-1];
    tr1.Ins(fa,u,a[u]);
    for(int i=head[u];i;i=e[i].nxt){
        int v=e[i].to;
        if(v==fa)continue;
        dfs(v,u);siz[u]+=siz[v];
    }
}
int LCA(int u,int v){
    if(dep[u]<dep[v])u^=v^=u^=v;
    for(int i=22;i>=0;--i)
        if(dep[f[u][i]]>=dep[v])u=f[u][i];
    if(u==v)return u;
    for(int i=22;i>=0;--i)
        if(f[u][i]!=f[v][i])
            u=f[u][i],v=f[v][i];
    return f[u][0];
}
void work(){
    int x,y,z;
    scanf("%d%d%d",&x,&y,&z);
    int A=LCA(x,y);
    printf("%d\n",tr1.UQT(x,y,A,f[A][0],z));
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        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);
            add(u,v);add(v,u);
        }
        dfs(1,0);
        for(;m;m--)work();
        memset(a,0,sizeof(a));
        dfstime=0;tot=0;
        memset(dfn,0,sizeof(dfn));
        memset(pre,0,sizeof(pre));
        memset(dep,0,sizeof(dep));
        memset(siz,0,sizeof(siz));
        memset(f,0,sizeof(f));
        memset(head,0,sizeof(head));
        tr1.clear();
    } 
    
    return 0;
}

\(Luogu:\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<1)+(s<<3)+(ch^48);
        ch=getchar();
    }
    return w==-1?-s:s;
}
int n,m,dep[MAXN],a[MAXN],siz[MAXN],dfn[MAXN];
int tot,ktot,head[MAXN<<1],pre[MAXN],f[MAXN][25];
struct edge{
    int nxt,to;
}e[MAXN<<1];
inline void add(int x,int y){
    e[++tot].to=y;
    e[tot].nxt=head[x];
    head[x]=tot;
}
struct Trie{
    int son[MAXN<<5][2],cnt=1,root[MAXN],ct[MAXN<<5];
    void Insert(int &rt,int x,int T){
        ct[++cnt]=ct[rt]+1,son[cnt][0]=son[rt][0];
        son[cnt][1]=son[rt][1];rt=cnt;
        if(T==-1)return;
        bool y=(x>>T)&1;
        Insert(son[rt][y],x,T-1);
    }
    inline void Ins(int pre,int rt,int x){
        root[rt]=root[pre];
        Insert(root[rt],x,30);
    }
    int Q(int i,int j,int x,int T){
        if(T==-1)return 0;
        bool y=(x>>T)&1;
        if(ct[son[j][1^y]]>ct[son[i][1^y]])return ((1<<T)+Q(son[i][1^y],son[j][1^y],x,T-1));
        return Q(son[i][y],son[j][y],x,T-1);
    }
    int QT(int i,int j,int lc,int flc,int x,int T){
        if(T==-1)return 0;
        bool y=(x>>T)&1;
        if(ct[son[j][1^y]]+ct[son[i][1^y]]>ct[son[lc][1^y]]+ct[son[flc][1^y]])return ((1<<T)+QT(son[i][1^y],son[j][1^y],son[lc][1^y],son[flc][1^y],x,T-1));
        else return QT(son[i][y],son[j][y],son[lc][y],son[flc][y],x,T-1);
    }
    int query(int l,int r,int x){return Q(root[l-1],root[r],x,30);}
    int UQT(int i,int j,int lc,int flc,int x,int T){
        return QT(root[i],root[j],root[lc],root[flc],x,T);
    }
}tr1,tr2;
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;f[u][0]=fa;
    dfn[u]=++ktot;pre[ktot]=u;
    tr1.Ins(fa,u,a[u]);siz[u]=1;
    for(int i=1;i<=22;++i)f[u][i]=f[f[u][i-1]][i-1];
    for(int i=head[u];i;i=e[i].nxt){
        int j=e[i].to;
        if(j==fa)continue;
        dfs(j,u);siz[u]+=siz[j];
    }
}
int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=22;i>=0;--i)
        if(dep[f[x][i]]>=dep[y])x=f[x][i];
    if(x==y)return x;
    for(int i=22;i>=0;--i)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    return f[x][0];
}

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;++i)a[i]=read();
    for(int i=1;i<n;++i){
        int u=read(),v=read();
        add(u,v);add(v,u);
    }
    dfs(1,0);
    for(int i=1;i<=n;++i)tr2.Ins(i-1,i,a[pre[i]]);
    for(;m;--m){
        int opt=read();
        if(opt==1){
            int x=read(),y=read();
            printf("%d\n",tr2.query(dfn[x],dfn[x]+siz[x]-1,y));
        }
        else {
            int x=read(),y=read(),z=read(),A=LCA(x,y);
            printf("%d\n",tr1.UQT(x,y,A,f[A][0],z,30));
        }
    }
    return 0;
} 
上一篇:jQuery基础及选择器(1)


下一篇:Vue+ajax实现三级联动