• 「刷题」幸运数字


    正解线性基。

    总的来说和lca一样,预处理出f[x][i]为x一直到x向根走 $ 2^i $ 步的合并线性基,

    那么可以和lca一样进行处理和合并,从而得到路径的线性基。

    再进行操作即可。

    不过我没有控memset,卡常卡了半天都没过,最后改了下memset就A了。

    卡常真的恶心。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define clear(a) memset((a).d,0,sizeof((a).d))
    using namespace std;
    
    
    typedef long long ll;
    const int maxn=2e4+5;
    ll n,q,x,y;
    ll w[maxn];
    char xB[(1<<15)+10],*xS=xB,*xT=xB;
    #define gtc (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
    inline void read(ll &x){
      register char ch=gtc;
      for(x=0;ch<'0'||ch>'9';ch=gtc);
      for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc);
    }
    inline void print(ll x)
    {
        if(x<0) {putchar('-'); x=-x;}
        if(x>9) print(x/10);
        putchar(x%10+48);
        return;
    }
    struct Road{
        int tot,t[maxn<<1],nxt[maxn<<1],first[maxn];
        void add(int x,int y)
        {
            t[++tot]=y;
            nxt[tot]=first[x];
            first[x]=tot;
        }
    }eage;
    struct Least_Common_Ancetor{
        struct line_bsis{
            ll d[63];
            void insert(ll x)
            {
                for(register int i=61;i>=0;i--)
                    if((x>>i)&1)
                    {
                        if(!d[i]) {d[i]=x;break;}
                        x^=d[i];
                    }
            }
            ll ma()
            {
                ll ans=0;
                for(register int i=61;i>=0;i--)
                    if((ans^d[i])>ans)
                        ans^=d[i];
                return ans;
            }
        }lb[maxn][30],own[maxn],tmp,r;
        int p,d[maxn],f[maxn][30];
        inline line_bsis merge(const line_bsis &a,const line_bsis &b)
        {
            clear(r);
            for(register int i=60;i>=0;i--)
            {
                if(a.d[i]) r.insert(a.d[i]);
                if(b.d[i]) r.insert(b.d[i]);
            }
            return r;
        }
        inline void lmerge(line_bsis &a,line_bsis &b)
        {
            for(register int i=60;i>=0;--i)
                if(b.d[i])
                    a.insert(b.d[i]);
        }
        void init()
        {
            p=log2(n)+1;
            for(int i=1;i<=n;i++) own[i].insert(w[i]);
            dfs(1,0);
        }
        inline void dfs(int x,int fa)
        {
            for(int i=eage.first[x];i;i=eage.nxt[i])
                if(eage.t[i]!=fa)
                {
                    int t=eage.t[i];
                    d[t]=d[x]+1;
                    f[t][0]=x;lb[t][0]=merge(own[x],own[t]);
                    for(int j=1;j<=p;j++)
                    {
                        f[t][j]=f[f[t][j-1]][j-1];
                        if(f[t][j]==0) break;
                        lb[t][j]=merge(lb[t][j-1],lb[f[t][j-1]][j-1]);
                    }
                    dfs(t,x);
                }
        }
        inline int LCA(int x,int y)
        {
            clear(tmp);
            if(d[x]<d[y]) swap(x,y);
            int t=d[x]-d[y];
            for(int i=p;t;i--)
                if(t&(1<<i))
                {
                    lmerge(tmp,lb[x][i]);
                    x=f[x][i];t^=(1<<i);
                }
            if(x==y) return x;
            for(int i=p;i>=0;i--)
                if(f[x][i]^f[y][i])
                {
                    lmerge(tmp,lb[x][i]);
                    lmerge(tmp,lb[y][i]);
                    x=f[x][i];y=f[y][i];
                }
            lmerge(tmp,lb[x][0]);
            lmerge(tmp,lb[y][0]);
            return f[x][0];
        }
    }zt;
    int main()
    {
        read(n);read(q);
        for(int i=1;i<=n;i++) read(w[i]);
        for(int i=1;i<=n-1;i++)
        {
            read(x);read(y);
            eage.add(x,y);eage.add(y,x);
        }
        zt.init();
        /*for(int i=1;i<=n;i++)
            for(int j=0;j<=zt.p;j++)
                cout<<i<<":"<<j<<" "<<zt.lb[i][j].ma()<<endl;*/
        while(q--)
        {
            read(x);read(y);
            if(x==y)
            {
                print(zt.own[x].ma());puts("");
                continue;
            }
            zt.LCA(x,y);
            print(zt.tmp.ma());puts("");
        }
        return 0;
    }
    幸运数字
  • 相关阅读:
    水仙花数
    Edge browser hosts file
    tt0034583
    JavaScript中的面向对象
    滚动
    无缝滚动
    MySQL(一)
    JavaScript 精粹
    MYSQL新手入门篇
    用github来展示你的前端页面吧
  • 原文地址:https://www.cnblogs.com/Lrefrain/p/11222907.html
Copyright © 2020-2023  润新知