TJOI2018 异或

题目链接:戳我

可持久化01trie+树链剖分

其实序列上的大家应该都会做,这个题还不过是把序列上的放到了树上而已。多来一个树剖就可以解决。

dummyummy说可以不用树剖写。。可是我还是不怎么会。。。等他写完了我再放那种解法的吧。。。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 200010
using namespace std;
int n,m,t,dfn,tot;
int head[MAXN<<1],wt[MAXN],rt[MAXN],ch[MAXN*32][2],cnt[MAXN*32];
int siz[MAXN],id[MAXN],w[MAXN],fa[MAXN],son[MAXN],top[MAXN],dep[MAXN];
struct Edge{int nxt,to;}edge[MAXN<<1];
inline void add(int from,int to)
{
    edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;
    edge[++t].nxt=head[to],edge[t].to=from,head[to]=t;
}
inline void dfs1(int x,int pre)
{
    siz[x]=1;
    fa[x]=pre;
    dep[x]=dep[pre]+1;
    int maxx=-1;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==pre) continue;
        dfs1(v,x);
        siz[x]+=siz[v];
        if(siz[v]>maxx) maxx=siz[v],son[x]=v;
    }
}
inline void dfs2(int x,int topf)
{
    top[x]=topf;
    id[x]=++dfn;
    w[dfn]=wt[x];
    if(son[x]) dfs2(son[x],topf);
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
    }
}
inline void insert(int x,int f,int sum)
{
    for(int i=31;i>=0;i--)
    {
        int v=((sum>>i)&1);
        ch[x][!v]=ch[f][!v];
        ch[x][v]=++tot;
        cnt[ch[x][v]]=cnt[ch[f][v]]+1;
        x=ch[x][v],f=ch[f][v];
    }
}
inline int query(int f,int x,int sum)
{
    int cur_ans=0;
    for(int i=31;i>=0;i--)
    {
        int v=((sum>>i)&1);
        if(cnt[ch[x][!v]]>cnt[ch[f][!v]])
        {
            cur_ans+=(1<<i);
            x=ch[x][!v],f=ch[f][!v];
        }
        else x=ch[x][v],f=ch[f][v];
    }
    return cur_ans;
}
inline int solve(int x,int y,int z)
{
    int cur_ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        cur_ans=max(cur_ans,query(rt[id[top[x]]-1],rt[id[x]],z));
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    cur_ans=max(cur_ans,query(rt[id[x]-1],rt[id[y]],z));
    return cur_ans;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    #endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&wt[i]);
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    dfs1(1,0);
    dfs2(1,1);
    rt[0]=++tot;
    insert(rt[0],0,0);
    //for(int i=1;i<=n;i++) printf("i=%d fa=%d w=%d\n",i,fa[i],w[i]);
    //for(int i=1;i<=n;i++) printf("i=%d id=%d siz=%d\n",i,id[i],siz[i]);
    for(int i=1;i<=n;i++) rt[i]=++tot,insert(rt[i],rt[i-1],w[i]);
    //for(int i=1;i<=n;i++) printf("rt[%d]=%d\n",i,rt[i]);
    for(int i=1;i<=m;i++)
    {
        int op,x,y,z;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d%d",&x,&y);
            //printf("op=%d x=%d y=%d\n",op,x,y);
            printf("%d\n",query(rt[id[x]-1],rt[id[x]+siz[x]-1],y));
        }
        else
        {
            scanf("%d%d%d",&x,&y,&z);
            //printf("op=%d x=%d y=%d z=%d\n",op,x,y,z);
            printf("%d\n",solve(x,y,z));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fengxunling/p/10485657.html