bzoj 4568 洛谷 3292 loj 2013 [SCOI2016]幸运数字 题解

博客观赏效果更佳

题意简述

给定一颗 n < = 20000 n<=20000 个点的树,点带点权,不超过 2 6 0 2^60 。还有 Q < = 200000 Q<=200000 个询问,每次询问两个点之间路径上的最大异或和。

思路

B [ i ] [ k ] B[i][k] 表示从 i i 往上 2 k 2^k 个节点组成的线性基。 L C A LCA 的时候线性基合并就珂以了。带三个log,两个是 l o g 2 60 log2^{60} ,一个是 l o g n logn 。也就是 O ( 200000 × 60 × 60 × 16 ) O(200000\times 60\times 60\times 16) 。虽然看起来有 1 e 9 1e9 ,但是你相信我那两个 60 60 乘不满。所以你能过。在 b z o j bzoj 的机器上写面向对象都能过。

代码细节

这题重在模拟。代码细节蛮多的。

  1. lca的第一步,跳到同一高度,判断条件是deep[fa[u][k]]<=deep[v]
  2. lca的最后一步,要把val[u],val[v],val[fa[u][0]]的值都插入进来。联想一下求最小值你就明白这步了
  3. 好像没了?代码还是蛮长的,别写挂别的地方即珂

代码

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
    #define N 24444
    #define int long long 
    #define F(i,l,r) for(int i=l;i<=r;++i)
    #define D(i,r,l) for(int i=r;i>=l;--i)
    #define Fs(i,l,r,c) for(int i=l;i<=r;c)
    #define Ds(i,r,l,c) for(int i=r;i>=l;c)
    #define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
    #define MEM(x,a) memset(x,a,sizeof(x))
    #define FK(x) MEM(x,0)

    class LB
    {
    public:
        int d[64];
        int& operator[](int id){return *(d+id);}
        void Init(){FK(d);}
        void Insert(int x)
        {
            D(i,60,0)
            {
                if (!(x&(1ll<<i))) continue;

                if (!d[i])
                {
                    d[i]=x;break;
                }
                x^=d[i];
            }
        }
        int MaxXor()
        {
            int ans=0;
            D(i,60,0) if ((ans^d[i])>ans) ans^=d[i];
            return ans;
        }
    };
    LB Merge(LB a,LB b)
    {
        D(i,60,0)
        {
            if (b[i]) a.Insert(b[i]);
        }
        return a;
    }
    class Graph
    {
        public:
            int head[N];
            int EdgeCount;
            struct Edge
            {
                int To,Label,Next;
            }Ed[N<<1];
            void clear(int _V=N,int _E=N<<1) 
            {
                memset(Ed,-1,sizeof(Edge)*(_E));
                memset(head,-1,sizeof(int)*(_V));
                EdgeCount=-1;
            }
            void AddEdge(int u,int v,int w=1)
            {
                Ed[++EdgeCount]=(Edge){v,w,head[u]};
                head[u]=EdgeCount;
            }
            void Add2(int u,int v,int w=1) {AddEdge(u,v,w);AddEdge(v,u,w);}
            int Start(int u) {return head[u];}
            int To(int u){return Ed[u].To;}
            int Label(int u){return Ed[u].Label;}
            int Next(int u){return Ed[u].Next;}
    }G;
    void R1(int &x)
    {
        x=0;char c=getchar();int f=1;
        while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        x=(f==1)?x:-x;
    }
    int n,m;int val[N];
    void Input()
    {
        R1(n),R1(m);
        F(i,1,n) R1(val[i]);
        G.clear();
        F(i,1,n-1)
        {
            int u,v;R1(u),R1(v);
            G.Add2(u,v);
        }
    }

    LB B[N][18];
    int fa[N][24],deep[N];
    void DFS(int u,int f)
    {
        deep[u]=deep[f]+1;
        fa[u][0]=f;
        B[u][0].Init();B[u][0].Insert(val[u]);
        F(i,1,16)
        {
            fa[u][i]=fa[fa[u][i-1]][i-1];
            B[u][i]=Merge(B[u][i-1],B[fa[u][i-1]][i-1]);
        }
        
        Tra(i,u)
        {int v=__v;
            if (v==f) continue;
            DFS(v,u);
        }
    }

    int LCA(int u,int v)
    {
        LB ans;ans.Init();
        if (deep[u]<deep[v]) swap(u,v);
        D(i,16,0)
        {
            if (deep[fa[u][i]]>=deep[v]) 
            {
                ans=Merge(ans,B[u][i]);
                u=fa[u][i];
            }
        } 

        if (u==v)
        {
            ans.Insert(val[u]);
            return ans.MaxXor();
        }

        D(i,16,0)
        {
            if (fa[u][i]!=fa[v][i])
            {
                ans=Merge(ans,B[u][i]);
                ans=Merge(ans,B[v][i]);
                u=fa[u][i],v=fa[v][i];
            }
        }
        ans.Insert(val[u]);ans.Insert(val[v]);
        ans.Insert(val[fa[u][0]]);
        return ans.MaxXor();
    }
    void Soviet()
    {
        DFS(1,1);

        F(i,1,m)
        {
            int u,v;R1(u),R1(v);
            printf("%lld\n",LCA(u,v));
        }
    }

    #define Flan void
    Flan IsMyWife()
    {
        Input();
        Soviet();
    }
    #undef int //long long 
}
int main()
{
    Flandre_Scarlet::IsMyWife();
    getchar();getchar();
    return 0;
}
发布了210 篇原创文章 · 获赞 8 · 访问量 8982

猜你喜欢

转载自blog.csdn.net/LightningUZ/article/details/103439882
今日推荐