学习线性基 bzoj 4568 幸运数字

来源:互联网 发布:苹果mac没有声音 音频 编辑:程序博客网 时间:2024/06/07 01:18

好久没写博客了,最近学习了一下新姿势:线性基,这个就很厉害了。

线性基其实很好理解。

会线性基可以直接跳过下面的部分。。。

我们先抛出一道简单的题:
给你一个长度为n的序列,在其中任选数字求可以得到的最大异或和。

我们知道任意两个,和连续一段的最大异或和,可以用Trie加贪心水掉,但这道题怎么做呢?

线性基就可以用来处理这个玩意。

通俗的讲:线性基其实是一些数的集合,而用这些集合里的数字任意组合异或可以表示完原数列中所有数字异或的情况。

而线性基中的数字有个重要性质就是 不会存在有两个数他们的二进制最高位相同。
所以线性基集合大小最多不会超过原数列中最大数的二进制位数。这个是显然的。

让我们先来讲如何构造线性基集合,考虑对于一个数x,如果x最高位在线性基集合中没有的话,就直接扔进去,否则就把x异或上那个存在的数,一直进行下去。

这是代码:其中Greed数组就表示了线性基集合。

inline void Greed_insert(ll x) {    if( !x ) return;    for(int i = 61; i >= 0; i--)     if(x & (1LL<<i)) {        if( !Greed[i]) {            Greed[i] = x;            break;        }        else x ^= Greed[i];    }}

我们再来讲讲它为什么可以表示完原来序列的所有情况。

假如我们要加入b,它的最高位是i,原来在这一位上已经存在一个数a了,那么我们令c=b^a,如果我们把c加进去c^a就可以表示出原来的b了所以我们加入c进去不会缺失所有异或的情况(也就是说可以凑出a,b,a^b)。

是不是非常easy。

让我们回到这道题上面:

这道题题意其实就是:我们把原来序列上的问题转换到了树上来做,现在每次询问问你u到v路径上的最大异或和。
其实做法差不多,只需要加一个st表,每次询问暴力合并线性基就可以了(一个一个插进去)。

ac代码,可能有点丑。

#include <cstdio>#include <algorithm>#include <vector>#include <cstring>#include <iostream>using namespace std;#define N 20005#define ll long long#ifdef WIN32 #define AUTO "%I64d"#else #define AUTO "%lld"#endifstruct Edge {    int v, next;};Edge e[2 * N];int n, m, fa[N][20], a, b, num, head[N], dep[N];ll aa[N], XOR[N][20][62];inline void adde(int i, int j) {    e[++num].v = j;    e[num].next = head[i];    head[i] = num;}inline void insert(ll x, int u, int k) {    if( !x ) return;    for(int i = 61; i >= 0; i--)     if(x & (1LL<<i)) {        if( !XOR[u][k][i]) {            XOR[u][k][i] = x;            break;        }        else x ^= XOR[u][k][i];    }}inline void dfs(int u) {    for(int i = head[u]; i; i = e[i].next) {        int v = e[i].v;        if(v == fa[u][0]) continue;        fa[v][0] = u;        insert(aa[u], v, 0);        insert(aa[v], v, 0);        dep[v] = dep[u] + 1;        dfs(v);    }}ll Greed[62];inline void Greed_insert(ll x) {    if( !x ) return;    for(int i = 61; i >= 0; i--)     if(x & (1LL<<i)) {        if( !Greed[i]) {            Greed[i] = x;            break;        }        else x ^= Greed[i];    }}ll _Greed() {    ll rt = 0;    for(int i = 61; i >= 0; i--)        if( (rt ^ Greed[i]) > rt ) rt ^= Greed[i];    return rt;}ll solv(int u, int v) {    if(u == v) return aa[u];    if(dep[u] < dep[v]) swap(u, v);    int len = dep[u] - dep[v];    for(int p = 0; len; p++, len >>= 1) {        if(len & 1) {            for(int k = 0; k <= 61; k++)            Greed_insert(XOR[u][p][k]);            u = fa[u][p];        }    }    if( u == v ) return _Greed();    for(int j = 18; j >= 0; j--) {        if(fa[u][j] == fa[v][j]) continue;        for(int k = 0; k <= 61; k++)        Greed_insert(XOR[u][j][k]),        Greed_insert(XOR[v][j][k]);        u = fa[u][j];        v = fa[v][j];    }    for(int k = 0; k <= 61; k++)    Greed_insert(XOR[u][0][k]),    Greed_insert(XOR[v][0][k]);    return _Greed();}int main() {    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; i++)    scanf(AUTO, &aa[i]);    for(int i = 1; i < n; i++) {        scanf("%d%d", &a, &b);        adde(a, b);        adde(b, a);    }    fa[1][0] = 1;    dfs(1);    for(int j = 1; j <= 18; j++) {        for(int i = 1; i <= n; i++) {            fa[i][j] = fa[fa[i][j-1]][j-1];            for(int k = 0; k <= 61; k++) {                insert(XOR[i][j-1][k], i, j);                insert(XOR[fa[i][j-1]][j-1][k], i, j);            }        }    }    while(m--) {        memset(Greed, 0, sizeof Greed);        scanf("%d%d", &a, &b);        printf(AUTO"\n", solv(a, b));    }    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机qq音乐闪退怎么办 qq音乐总是闪退怎么办 手机qq音乐闪退怎么办修复 苹果7p耳机漏音怎么办 akgn25耳机盖掉了怎么办 外汇平台跑路了怎么办 微云资料没了怎么办 酷狗k歌有杂音怎么办 手机k歌音质不好怎么办 酷狗让升级内测取消之后怎么办 苹果5s声音太小怎么办 苹果6p调均衡卡怎么办 忘记密码怎么办登录云教育 登录微信收不到验证码怎么办 红米手机黑白屏怎么办 手机登录不上电子邮件怎么办 如果台湾发生骚乱大陆怎么办 80端口被占用了怎么办? qq邮箱服务器密码忘记了怎么办 对方身份异常请验证怎么办 qq附近人屏蔽了怎么办 快递地址填错了怎么办 快递填错地址已经发货怎么办 淘宝受到卖家威胁怎么办 消费者被外卖商家威胁怎么办 拼多多商家打电话威胁怎么办 退款被拒商家还威胁怎么办? 打错电话给领导怎么办 领导送礼物给我怎么办 南瓜饼和面很稀怎么办 包饺子剩的肉馅怎么办 发好的面团粘手怎么办 富士变频器减速时间过电流怎么办 铺木地板地面不是很平怎么办 眼镜被铁锈烫了怎么办 平车机针头小了怎么办 mk包五金坏了怎么办 迁坟原来的棺材怎么办 新建定额项目没有措施项目怎么办 太岁符忘记烧了怎么办 穿裙子去了寺庙怎么办