zoukankan      html  css  js  c++  java
  • BZOJ 4568 幸运数字

    SCOI血泪史第二部。。

    倍增+合并线性基。

    时间又垫底啦。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #define maxv 20050
    #define maxe 40050
    using namespace std;
    long long n,q,w[maxv],nume=0,g[maxv],x,y,anc[maxv][16],dis[maxv],fath[maxv];
    long long regis[65],table[65];
    long long k1[65],k2[65];
    struct edge
    {
        long long v,nxt;
    }e[maxe];
    struct base
    {
        long long ins[65];
    }r[maxv][16];
    void gettable()
    {
        table[0]=1;
        for (int i=1;i<=60;i++)
            table[i]=table[i-1]<<1;
    }
    void clear()
    {
        for (int i=0;i<=15;i++)
            for (int j=0;j<=60;j++)
                r[0][i].ins[j]=0;
    }
    void addedge(long long u,long long v)
    {
        e[++nume].v=v;
        e[nume].nxt=g[u];
        g[u]=nume;
    }
    void dfs(long long x,long long father)
    {
        anc[x][0]=x;fath[x]=father;dis[x]=dis[father]+1;
        for (long long i=60;i>=0;i--)
        {
            if (w[x]&table[i])
            {
                r[x][0].ins[i]=w[x];
                break;
            }
        }
        for (long long i=g[x];i;i=e[i].nxt)
        {
            long long v=e[i].v;
            if (v!=father)
                dfs(v,x);
        }
    }
    void add(long long x,long long a,long long y,long long b)
    {
        memset(k1,0,sizeof(k1));
        memset(k2,0,sizeof(k2));
        int flag=1;
        for (int i=0;i<=60;i++)
        {
            k1[i]=r[x][a].ins[i];
            k2[i]=r[y][b].ins[i];
            if (!regis[i]) flag=0;
        }
        if (flag==1) return;
        for (long long i=0;i<=60;i++)
        {
            if (k1[i])
            {
                for (long long j=60;j>=0;j--)
                {
                    if (k1[i]&table[j])
                    {
                        if (!regis[j]) {regis[j]=k1[i];break;}
                        else k1[i]^=regis[j];
                    }
                }
            }
            if (k2[i])
            {
                for (long long j=60;j>=0;j--)
                {
                    if (k2[i]&table[j])
                    {
                        if (!regis[j]) {regis[j]=k2[i];break;}
                        else k2[i]^=regis[j];
                    }
                }
            }
        }
    }
    long long lca(long long x,long long y)
    {
        if (dis[x]<dis[y]) swap(x,y);
        for (long long e=15;e>=0;e--)
        {
            if (dis[fath[anc[x][e]]]>=dis[y])
                x=fath[anc[x][e]];
        }
        if (x==y) return x;
        for (long long e=15;e>=0;e--)
        {
            if (fath[anc[x][e]]!=fath[anc[y][e]])
            {
                x=fath[anc[x][e]];
                y=fath[anc[y][e]];
            }
        }
        return fath[x];
    }
    void work()
    {
        memset(regis,0,sizeof(regis));
        long long t=lca(x,y);
        for (long long e=15;e>=0;e--)    
        {
            if (dis[fath[anc[x][e]]]>=dis[t])
            {
                add(x,e,0,0);
                x=fath[anc[x][e]];
            }
        }
        for (long long e=15;e>=0;e--)
        {
            if (dis[fath[anc[y][e]]]>=dis[t])
            {
                add(y,e,0,0);
                y=fath[anc[y][e]];
            }
        }
        add(t,0,0,0);
        long long ans=0;
        for (long long i=60;i>=0;i--)
        {
            if ((ans^regis[i])>ans)
                ans^=regis[i];
        }
        printf("%lld
    ",ans);
    }
    int main()
    {
        gettable();
        scanf("%lld%lld",&n,&q);
        for (long long i=1;i<=n;i++)
            scanf("%lld",&w[i]);
        for (long long i=1;i<=n-1;i++)
        {
            scanf("%lld%lld",&x,&y);
            addedge(x,y);
            addedge(y,x);
        }
        dfs(1,0);
        clear();
        for (long long e=1;e<=15;e++)
        {
            for (long long i=1;i<=n;i++)
            {
                anc[i][e]=anc[fath[anc[i][e-1]]][e-1];
                memset(regis,0,sizeof(regis));
                add(i,e-1,fath[anc[i][e-1]],e-1);
                for (long long j=0;j<=60;j++)
                    r[i][e].ins[j]=regis[j];
            }
        }
        for (long long i=1;i<=q;i++)
        {
            scanf("%lld%lld",&x,&y);
            work();
        }
        return 0;
    }
  • 相关阅读:
    Java知识积累3-XML的DOM解析修改和删除方法
    Java知识积累-XML的DOM解析修改和删除方法
    Java知识积累2-StringReverse实现文字(单词)倒叙输出
    Java知识积累1-StringAlign实现文字居中左右对齐
    String中具有的方法
    有17个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下 的是原来第几号的那位
    编写一个程序,求出整数数组中最小元素的下标。如果这样的元素个数大于1,则返回下标最小的数的下标。
    初识
    关于点击跳转页面
    sql存储过程
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5561275.html
Copyright © 2011-2022 走看看