P3292 [SCOI2016]幸运数字

删除回忆录丶 提交于 2020-02-23 13:17:11

题目链接

题意分析

一句话题意 : 树上一条链中挑选出某些数 异或和最大

我们可以考虑维护一个树上倍增线性基

然后倍增的时候 维护一个线性基合并就可以了

写起来还是比较容易的

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 200008
#define IL inline
#define M 66
#define D double
#define ull unsigned long long
#define R register
using namespace std;
template<typename T>IL void read(T &_)
{
    T __=0,___=1;char ____=getchar();
    while(!isdigit(____)) {if(____=='-') ___=0;____=getchar();}
    while(isdigit(____)) {__=(__<<1)+(__<<3)+____-'0';____=getchar();}
    _=___ ? __:-__;
}
/*-------------OI使我快乐-------------*/
int n,m,tot;
int to[N<<1],nex[N<<1],head[N];
int dep[N],fath[N][20];
ll num[N],ans[M],key[N][20][M];
IL void add(int x,int y)
{to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
IL void insert(ll *x,ll y)
{
    for(R int i=61;i>=0;--i)
    {
        ll now=(1ll<<i);
        if(now&y)
        {
            if(!x[i]) {x[i]=y;break;}
            y^=x[i];
        }
    }
}
IL void merge(ll *cdy,ll *wzy)
{
    for(R int i=61;i>=0;--i) if(cdy[i]) insert(wzy,cdy[i]);
}
IL ll qury_ans()
{
    ll res=0;
    for(R int i=61;i>=0;--i)
    if((res^ans[i])>res) res^=ans[i];
    return res;
}
IL void dfs(int now,int fat)
{
    fath[now][0]=fat;dep[now]=dep[fat]+1;
    insert(key[now][0],num[now]);
    for(R int i=1;(1<<i)<=dep[now];++i)
    {//倍增 + 合并线性基
        fath[now][i]=fath[fath[now][i-1]][i-1];
        merge(key[now][i-1],key[now][i]);
        merge(key[fath[now][i-1]][i-1],key[now][i]);
    }
    for(R int i=head[now];i;i=nex[i])
    {
        int v=to[i];
        if(v==fat) continue;
        dfs(v,now);
    }
}
IL ll qury_LCA(int nowx,int nowy)
{//倍增 + 维护答案线性基
    memset(ans,0,sizeof ans);
    if(dep[nowx]<dep[nowy]) swap(nowx,nowy);
    for(R int i=19;i>=0;--i)
    {
        if(dep[fath[nowx][i]]>=dep[nowy])
        {
            merge(key[nowx][i],ans);
            nowx=fath[nowx][i];
        }
    }
    if(nowx==nowy)
    {
        insert(ans,num[nowx]);
//      insert(ans,num[nowx]);
//      insert(ans,num[fath[nowx][0]]);
        return qury_ans();
    } 
    for(R int i=19;i>=0;--i)
    {
        if(fath[nowx][i]!=fath[nowy][i])
        {
            merge(key[nowx][i],ans);
            merge(key[nowy][i],ans);
            nowx=fath[nowx][i];nowy=fath[nowy][i];
        }
    }
    insert(ans,num[nowx]);
    insert(ans,num[nowy]);
    insert(ans,num[fath[nowx][0]]);
//  insert(ans,num[nowx]);
//  insert(ans,num[fath[nowx][0]]); 
//  insert(ans,num[nowy]);
//  insert(ans,num[fath[nowy][0]]); 
    return qury_ans();
}
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n);read(m);
    for(R int i=1;i<=n;++i) read(num[i]);
    for(R int i=1,x,y;i<n;++i)
    {
        read(x);read(y);
        add(x,y);add(y,x);
    }
    dfs(1,0);
    while(m--)
    {
        int x,y;
        read(x);read(y);
        printf("%lld\n",qury_LCA(x,y));
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!