zoukankan      html  css  js  c++  java
  • Love Live!-01字典树启发式合并

    链接:https://ac.nowcoder.com/acm/contest/201/D?&headNav=www

    思路:题目要求的是每个等级下的最大 简单路径中的最大异或值,那么我们为了保证目前的路径中最大的权值

    为当前访问的边,先进行排序,然后一条一条的插入边,并查集维护  各个联通块,启发式合并,由当前边连接起来的

    两个联通块,所谓启发式合并也就是 把小的块 合并到大的上。然后 查询的时候就是再当前 这条边的两个联通块中

    找一个包含此边的 最大异或路径,  为了方便处理 我们可以把每个点 存储一个到 它并查集根节点的 异或值,

    这样进行 0 1 字典树维护即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 234567
    vector<int>gra[maxn];
    int tree[maxn*100][3],ans[maxn];
    int n,m,u,v,w,root[maxn],tx,ty;
    int fa[maxn],val[maxn],tot,sz[maxn];
    struct node
    {
        int x,y,w;
        bool operator<(const node &b)const
        {
            return w<b.w;
        }
    } edge[maxn];
    int fond(int x)
    {
        return x==fa[x]?x:fa[x]=fond(fa[x]);
    }
    void updata(int x,int ad)
    {
        for(int i=20; i>=0; i--)
        {
            int id=((1<<i)&ad)?1:0;
            if(!tree[x][id])
                tree[x][id]=++tot;
            x=tree[x][id];
        }
    }
    int query(int x,int ad)
    {
        int ret=0;
        for(int i=20; i>=0; i--)
        {
            int id=((1<<i)&ad)?1:0;
            if(tree[x][id^1])
            {
                x=tree[x][id^1];
                ret|=(1<<i);
            }
            else x=tree[x][id];
        }
        return ret;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1; i<n; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            edge[i]=(node{u,v,w});
        }
        sort(edge+1,edge+n);
        for(int i=1; i<=n; i++)
        {
            fa[i]=i;
            sz[i]=1;
            gra[i].push_back(i);
            root[i]=++tot;
            updata(root[i],0);
        }
        for(int i=1; i<n; i++)
        {
            u=edge[i].x,tx=fond(u);
            v=edge[i].y,ty=fond(v);
            w=(edge[i].w^val[u]^val[v]);
            if(sz[tx]>sz[ty])swap(tx,ty),swap(u,v);
            for(int j=0; j<sz[tx]; j++)
                ans[i]=max(ans[i],query(root[ty],(w^val[gra[tx][j]])));
            for(int j=0; j<sz[tx]; j++)
            {
                val[gra[tx][j]]^=w;
                gra[ty].push_back(gra[tx][j]);
                updata(root[ty],val[gra[tx][j]]);
            }
            fa[tx]=ty;
            sz[ty]+=sz[tx];
        }
        for(int i=1; i<n; i++)
        {
            printf("%d",ans[i]);
            if(i!=n-1)printf(" ");
            else printf("
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    css3中的位置移动
    css中伪元素选择器
    css中伪类选择器
    html5之属性选择器
    html5的文本属性
    html5的视频和音频使用
    常用的linux命令
    常见的http状态码
    springboot之安装和启动es
    linux版本的jdk安装
  • 原文地址:https://www.cnblogs.com/SDUTNING/p/10302518.html
Copyright © 2011-2022 走看看