AC日记——「SCOI2016」幸运数字 LiBreOJ 2013

「SCOI2016」幸运数字

 

思路:

  线性基;

 

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 20005
#define ll long long
struct DataType {
    ll d[61],p[61];
    ll cnt;
    DataType()
    {
        memset(d,0,sizeof(d));
        memset(p,0,sizeof(p));
        cnt=0;
    }
    bool insert(long long val)
    {
        for(ll i=60;i>=0;i--)
        {
            if(val&(1LL<<i))
            {
                if(!d[i])
                {
                    d[i]=val;
                    break;
                }
                val^=d[i];
            }
        }
        return val>0;
    }
    ll Max()
    {
        ll res=0;
        for(ll i=60;i>=0;i--)
        {
            if((res^d[i])>res) res^=d[i];
        }
        return res;
    }
};
struct DataType ans;
struct TreeNodeType {
    ll l,r,mid;
    DataType data;
};
struct TreeNodeType tree[maxn<<2];
ll n,m,deep[maxn],id[maxn],size[maxn],f[maxn],head[maxn];
ll E[maxn<<1],V[maxn<<1],tot,ai[maxn],bi[maxn],lar[maxn];
ll top[maxn];
inline void in(ll &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0')Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}
void edge_add(ll u,ll v)
{
    E[++tot]=head[u],V[tot]=v,head[u]=tot;
    E[++tot]=head[v],V[tot]=u,head[v]=tot;
}
void merge(DataType &a,DataType b)
{
    for(ll i=0;i<=60;i++)
    {
        if(b.d[i]) a.insert(b.d[i]);
    }
}
void dfs1(ll now,ll fa)
{
    f[now]=fa,deep[now]=deep[fa]+1,size[now]=1;
    for(ll i=head[now];i;i=E[i])
    {
        if(V[i]==fa) continue;
        dfs1(V[i],now),size[now]+=size[V[i]];
        if(size[lar[now]]<size[V[i]]) lar[now]=V[i];
    }
}
void dfs2(ll now,ll chain)
{
    top[now]=chain,id[now]=++tot,bi[tot]=ai[now];
    if(lar[now])
    {
        dfs2(lar[now],chain);
        for(ll i=head[now];i;i=E[i])
        {
            if(V[i]==lar[now]||V[i]==f[now]) continue;
            dfs2(V[i],V[i]);
        }
    }
}
void build(ll now,ll l,ll r)
{
    tree[now].l=l,tree[now].r=r;
    if(l==r)
    {
        tree[now].data.insert(bi[l]);
        return;
    }
    tree[now].mid=l+r>>1;
    build(now<<1,l,tree[now].mid),build(now<<1|1,tree[now].mid+1,r);
    tree[now].data=tree[now<<1].data;
    merge(tree[now].data,tree[now<<1|1].data);
}
void query(ll now,ll l,ll r)
{
    if(tree[now].l>=l&&tree[now].r<=r)
    {
        merge(ans,tree[now].data);
        return;
    }
    if(l<=tree[now].mid) query(now<<1,l,r);
    if(r>tree[now].mid) query(now<<1|1,l,r);
}
ll query(ll x,ll y)
{
    for(int i=0;i<=60;i++) ans.d[i]=0,ans.p[i]=0;
    ans.cnt=0;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) query(1,id[top[y]],id[y]),y=f[top[y]];
        else query(1,id[top[x]],id[x]),x=f[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    query(1,id[x],id[y]);
    return ans.Max();
}
int main()
{
    freopen("data.txt","r",stdin);
    in(n),in(m);ll u,v;
    for(ll i=1;i<=n;i++) in(ai[i]);
    for(ll i=1;i<n;i++)in(u),in(v),edge_add(u,v);
    dfs1(1,0),tot=0,dfs2(1,1),build(1,1,n);
    while(m--) in(u),in(v),printf("%lld\n",query(u,v));
    return 0;
}

 

posted @ 2017-06-24 10:52  IIIIIIIIIU  阅读(331)  评论(0编辑  收藏  举报