首页 > 其他分享 >xor (牛客多校) (线性基+ 线段树)

xor (牛客多校) (线性基+ 线段树)

时间:2023-04-18 18:45:04浏览次数:33  
标签:xor int tree 多校 mid 牛客 异或 ui --

 

 思路:

  • 问xor起来有没有某个值, 想到线性基
  • 然后发现问L-R区间的集合都要表示x, 利用线性基的交集解决
  • 在利用线段树解决区间问题 
#include <iostream>
using namespace std;
typedef unsigned int ui;
const int maxn = 50005;
struct L_B{    //线性基结构体
    ui b[35];
    bool zero;    //判断能否异或出0
    void init(){
        zero = false;
        for(int i = 0; i <= 31; i++)    b[i] = 0;
    }
};
struct Node{
    L_B node;
    int l;
    int r;
};
Node tree[maxn << 2];
int n, m;
bool Insert(L_B &A, ui t){    //将t尝试插入线性基A,注意这里如果能插入返回false,否则返回true(这样写是为这道题改造的,一般情况是能插入返回true)
    if(t == 0){
        if(A.zero)    return true;
        else    return false;
    }
    for(int i = 31; i >= 0; i--){
        if(t & (1u << i)){
            if(A.b[i]){
                t ^= A.b[i];
            }else{
                A.b[i] = t;
                return false;
            }
        }
    }
    A.zero = true;
    return true;
}
L_B Merge(L_B A, L_B B){    //求线性基A与线性基B的交集。
    L_B C, ALL;
    C.init(), ALL.init();
    ui cnt[35];
    for(int i = 0; i <= 31; i++){
        C.b[i] = A.b[i];
        cnt[i] = (1u << i);
    }
    for(int i = 31; i >= 0; i--){
        ui v = B.b[i];
        if(v){
            ui temp = 0;
            bool can = true;
            for(int j = 31; j >= 0; j--){
                if(v & (1u << j)){
                    if(C.b[j]){
                        v ^= C.b[j];
                        temp ^= cnt[j];
                    }else{
                        can = false;
                        C.b[j] = v;
                        cnt[j] = temp;
                        break; 
                    }
                }
            }
            if(can){
                ui k = 0;
                for(int j = 31; j >= 0; j--){
                    if(temp & (1u << j)){
                        k ^= C.b[j];
                    }
                }
                Insert(ALL, k);
            }
        }
    }
    return ALL;
}
void build(int k, int l, int r){    //建树
    tree[k].l = l;
    tree[k].r = r;
    if(l == r){    //建立叶子节点
        int cnt;
        scanf("%d", &cnt);
        tree[k].node.init();
        for(int i = 1; i <= cnt; i++){
            ui t;
            scanf("%u", &t);        
            Insert(tree[k].node, t);    //往此叶子节点插入对应集合的值。
        }
        return;
    }
    int mid = (l + r) >> 1;
    build(2*k, l, mid);
    build(2*k+1, mid+1, r);
    tree[k].node = Merge(tree[2*k].node, tree[2*k+1].node);    //回溯就求左右子节点线性基的交集
    return;
}
bool query(int k, int l, int r, ui t){    //询问l到r区间内的集合是否都能异或出x
    if(l <= tree[k].l && r >= tree[k].r){
        L_B temp = tree[k].node;
        return Insert(temp, t);    //能异或出返回true
    }
    int mid = (tree[k].l + tree[k].r) >> 1;
    return (l <= mid? query(2*k, l, r, t): true) && (r > mid? query(2*k+1, l, r, t): true);    //返回mid的左右部分是否都能异或出x
}
int main(){
    scanf("%d%d", &n, &m);
    build(1, 1, n);
    while(m--){
        int l, r;
        ui x;
        scanf("%d%d%u", &l, &r, &x);
        if(x == 0 || query(1, l, r, x))    printf("YES\n");    //特判x=0一定能异或出(空集异或出0)
        else    printf("NO\n");
    }
    return 0;
} 
偷来的代码

后记:

  • 线性基的交集还没有解决

 

标签:xor,int,tree,多校,mid,牛客,异或,ui,--
From: https://www.cnblogs.com/Lamboofhome/p/17330716.html

相关文章

  • 牛客挑战赛67
    A构造分析:这个题目思维挺好的#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintM=1000005;intp[M];intmain(){ intn,a,b,t; cin>>t; while(t--) { cin>>n>>a>>b; p[a]=b; if(a<=n&&b<=n|......
  • sequence (牛客多校) (区间包含某个值的最大最小, 和那个东西)
     思路:一步一步的拆解分析有一个min(al...r)通过这个东西那么就可以根据这个ai值分区间,可以通过单调zhai处理当然也可以去利用启发式合并处理,  在处理区间的时候,因为这个有正负,要分类讨论正就是最大负数就是最小遇到区间包含某个值的区间最大最小那么就......
  • free (牛客多校) (dj最短路+dp优化处理)
    本题大意:给出n,m,s,t,k,n个点,m条路,求s到t的最短路,并且最多k条路免费,然后给出m行,u,v,w,代表u到v有一条权值为w的双向路。 思路:就是dj最短路+一个dp维度的处理,dp[i][j],到第i个节点用了多少个免费的路径的最短路径 ......
  • [牛客]链表中倒数第k个结点
    牛客链接使用快慢指针法:两种思路:1.fast先向后走k-1次,slow再向后走1次,然后fast和slow同时向后走,当fast走到最后一个结点时,slow刚好在倒数第k个位置上;2.fast先向后走k次,slow再向后走1次,然后fast和slow同时向后走,当fast走到最后一个结点的后面时(此时为NULL),slow刚好在倒数......
  • CF1816F Xor Counting - dp - 分治 -
    题目链接:https://codeforces.com/contest/1816/problem/F题解:一道有趣的题。首先发现\(m=1\)和\(m\geq3\)时结论是平凡的。\(m=1\)时结论显然,下面讨论一下\(m\geq3\)时:首先可以构造\([x,(n-x)/2,(n-x)/2,\cdots]\),其中\(x\)和\(n\)同奇偶,显然此时异或值可以......
  • 牛客练习110-D
    题目链接:https://ac.nowcoder.com/acm/contest/54129/D比赛的时候dp状态方程想错了,一直在做无用攻。思路:设\(dp[i]\)为用了i次魔法的期望值,递推地做即可。代码:#include<bits/stdc++.h>usingnamespacestd;constintmod=1e9+7;map<char,int>M;longlongqmod(longlong......
  • HDU 4864Task(多校联合训练1)(贪心)
    题目地址:HDU4864这题又是一上来认为是最小费用流,但是边太多,果然,敲完交上去后不断TLE。。小优化了两次也没过。。。sad。。后来看了题解才发现是贪心。。。贪心也不好想。大体思路是很好想的,就是先都按时间从大到小排序,再遍历任务,从机器里找能匹配的,并在能匹配的里边找等级尽量小的......
  • 牛客网一道素数问题
    我收回昨天的话,浪费时间或许不是能力问题,但是写出屎山,真真正正是能力问题今天编出来的程序破天荒地达到了34ms,然而大佬们都是1ms,于是点开大佬们的代码查看,发现他们的写法,他们使用的算法,寥寥几行代码,我看了半天不得其义,尝试着运行,非常流畅,让人目瞪口呆。多看一些代码之后,发现写法......
  • LRU management (牛客多校) (map+list)
        思路:利用map+list暴力模拟就彳于了#pragmaGCCoptimize(2)#include<bits/stdc++.h>usingnamespacestd;#defineIOSios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);#defineMAXN100001#defineINF(0x3f3f3f3f)#defineuintunsignedint#d......
  • Magic Line (牛客多校) (贪心,构造)
    题目大意:在平面直角坐标系中有偶数个点,求两个点使这两个点的连线两边点的数量相同且不经过任何一个点点的坐标都为整数,且绝对值不大于1000思路:我们先对点按横坐标排序,找到中间的两个点,如果这两个点横坐标不同,可以在两点之间找一条平行于y轴的直线如果相同的,因为点的纵坐标不......