zoukankan      html  css  js  c++  java
  • [SCOI2016]幸运数字

    洛谷

    倍增+线性基+lca

    我们可以发现线性基具有可合并性

    貌似st表也是可以的

    水题

    #include<bits/stdc++.h>
    #define re return
    #define ll long long 
    #define dec(i,l,r) for(ll i=l;i>=r;--i)
    #define inc(i,l,r) for(ll i=l;i<=r;++i) 
    using namespace std;
    template<typename T>inline void rd(T&x)
    {
        char c;bool f=0;
        while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
        x=c^48;
        while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
        if(f)x=-x;
    }
    
    const int maxn=20005;
    int n,m,k,fa[maxn][15],deep[maxn],hd[maxn];
    struct node
    {
        ll p[62];
        node merge(node b)//线性基合并
        {
            dec(i,61,0)
            {
                if(p[i])
                {
                    ll x=p[i];
                    dec(j,i,0)
                    if(x>>j)
                    {
                        if(!b.p[j])
                        {
                            b.p[j]=x;
                            break;
                        }
                        else x^=b.p[j];
                    }
                }
            }
            re b;
        }
        inline void insert(ll x)//线性基加入
        {
            dec(i,61,0)
            if(x>>i)
            {
                if(!p[i])
                {
                    p[i]=x;
                    break;
                }
                x^=p[i];
            }
         } 
        inline void clear()
        {
            memset(p,0,sizeof(p));
        }
        
        inline ll Get_max()//得到最大值
        {
            ll sum=0;
            dec(i,61,0)
            if((sum^p[i])>sum)
            sum^=p[i];
            re sum;
        }
    }dis[maxn][15],ans;
    
    struct ssl
    {
        int to,nt;
    }e[maxn<<1];
    
    inline void add(int x,int y)
    {
        e[++k].to=y;e[k].nt=hd[x];hd[x]=k;
        e[++k].to=x;e[k].nt=hd[y];hd[y]=k;
    }
    
    inline void dfs(int x)//dfs倍增预处理
    {
    
        deep[x]=deep[fa[x][0]]+1;
        for(int i=0;fa[fa[x][i]][i];++i)
        {
            fa[x][i+1]=fa[fa[x][i]][i];
            dis[x][i+1]=dis[x][i].merge(dis[fa[x][i]][i]);
        }
        
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(v==fa[x][0])continue;
            fa[v][0]=x;
            dfs(v);
        }
    }
    
    inline void LCA(int x,int y)//LCA求解
    {
        ans.clear();
        if(deep[x]<deep[y])x^=y^=x^=y;
        
        dec(i,14,0)
        if(deep[fa[x][i]]>=deep[y])
        {
            ans=ans.merge(dis[x][i]);
            x=fa[x][i];
        }
        if(x==y)
        {
            ans=ans.merge(dis[x][0]);
            re;
        }
        
        dec(i,14,0)
        if(fa[x][i]!=fa[y][i])
        {
            ans=ans.merge(dis[x][i]);
            ans=ans.merge(dis[y][i]);
            x=fa[x][i];y=fa[y][i];
        }
    
        ans=ans.merge(dis[y][0]);
        ans=ans.merge(dis[x][0]);
        ans=ans.merge(dis[fa[x][0]][0]);
        re ;
    }
    
    int main()
    {
        ll x,y;
        
        rd(n),rd(m);
        inc(i,1,n)
        {
            rd(x);
            dis[i][0].insert(x);
        }
        
        inc(i,2,n)
        {
            rd(x),rd(y);
            add(x,y);
        }
        dfs(1);
        
        inc(i,1,m)
        {
            rd(x),rd(y);
            LCA(x,y);
            printf("%lld
    ",ans.Get_max());
        }
        re 0;
    }
  • 相关阅读:
    java例程练习(简单的画图程序[鼠标事件处理])
    java例程练习(事件监听机制)
    java例程练习(布局管理器[FlowLayout])
    java例程练习(网络编程[简单UDP通信试验])
    java例程练习(BorderLayou&GridLayout)
    java例程练习(关于内部类的一个非常重要的作用)
    java例程练习(Graphics类[paint()方法])
    java例程练习(TextField)
    Service Broker 常见问题
    ubuntu8.04 和 Fedora 9
  • 原文地址:https://www.cnblogs.com/lsyyy/p/11552726.html
Copyright © 2011-2022 走看看