zoukankan      html  css  js  c++  java
  • 「2019冬令营提高组」密文

    传送门

    考虑前缀异或和 $b[i]$

    如果知道每个 $b[i]$ 就相当于知道所有数

    初始知道 $b[0]$,每次操作 $l,r$ 就是求出 $b[l-1] xor b[r]$

    考虑转化成图论模型,把 $b[i]$ 看成点(包括 $b[0]$),每次操作相当于把两个点 $b[l-1],b[r]$ 连边,边权为 $b[l-1] xor b[r]$

    当整个图变成一个联通块时就相当于求出了所有的 $b[i]$

    要求图联通时代价最小,显然考虑 prim 求最小生成树

    对于一个点 $u$,找一个点 $v$ 使得边权最小,显然可以用 $trie$ 来找

    但是每次都暴力搞还是太慢了,考虑贪心

    对于 $trie$ 上的一个节点,如果只考虑左儿子的联通块和右儿子的联通块合并,那么最小代价必然是左儿子子树中的一个叶子节点和右儿子子树中的一个叶子节点连起来

    那么对 $trie$ 上的每个节点 $u$,递归左右儿子,先让左右儿子的子树变成联通块,然后,枚举它左子树的每个叶子节点,然后暴力往右子树中查询最小值,最后把最小代价加到答案里

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e5+7;
    const ll INF=1e18+7;
    int n,b[N];
    int ch[N*31][2],rt,tot;//trie
    vector <int> G[N*31];//G存每个节点的子树所有叶子代表的b
    void insert(int &u,int x,int d)//插入
    {
        if(!u) u=++tot;
        G[u].push_back(x);
        if(d>=0) insert(ch[u][ (x>>d)&1 ],x,d-1);
    }
    int query(int u,int x,int d)//查询
    {
        if(d<0) return 0;
        if(ch[u][ (x>>d)&1 ]) return query(ch[u][ (x>>d)&1 ],x,d-1);
        else return query(ch[u][ ((x>>d)&1)^1 ],x,d-1) + (1<<d);
    }
    ll ans;
    void solve(int u,int d)//递归处理
    {
        if(d<0) return;
        if(ch[u][0]) solve(ch[u][0],d-1);
        if(ch[u][1]) solve(ch[u][1],d-1);
        if(ch[u][0]&&ch[u][1])
        {
            ll res=INF; int lc=ch[u][0],rc=ch[u][1];
            for(int i=G[lc].size()-1;i>=0;i--)
                res=min(res,1ll*query(rc,G[lc][i],d-1));
            ans+=res+(1<<d);
        }
    }
    int main()
    {
        freopen("secret.in","r",stdin);
        freopen("secret.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++) b[i]=b[i-1]^read();
        for(int i=0;i<=n;i++) insert(rt,b[i],29);//注意b[0]也要插入
        solve(rt,29);
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    React组件的Refs
    Typechecking With PropTypes
    酷炫Jquery收集
    JSTL函数标签库 fn标签学习
    Struts标签 比较时间大小
    Struts2 拦截器 配置IFrame页面跳转
    实体Bean, Entity 注解设置
    Uploadify 参数说明
    Uploadify jsp使用示例
    百度umeditor
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10548565.html
Copyright © 2011-2022 走看看