P4839 P 哥的桶
让我们拥抱随机化!
介绍一种 zky 随机化做法。
在看到这篇题解之后才发现我竟然去过 WC。
Solution
看到这题之后突然发现自己不会写线段树怎么办?
在 WC 2025 zky 的讲座上,zky 对于区间异或提出了这样一种做法:
考虑维护 \(100\) 个序列,每个序列的第 \(i\) 个元素有 \(\frac{1}{2}\) 的概率为 \(0\),有 \(\frac{1}{2}\) 的概率为 \(a_i\)。做查询时,只需对每个序列都求出区间异或和,然后假装这些元素形成的线性基是原区间的线性基即可。
正确性证明?不会可以参见我从课件上扒下来的这部分:
显然我们得到的线性基应是真正线性基的子空间。所以只需证明其有高概率是真正的线性基即可。
首先我们可以将证明归约至区间线性基恰好能表示 \([0,2^l − 1]\) 的情况。
如果我们的线性基不完整,那么一定存在一个 \(l\) 维向量 \(v\) 使得 \(v\) 和线性基中的所有元素点乘均为 \(0\)。这对于一个序列来说概率是 \(\frac{1}{2}\),\(100\) 个都满足就是 \(2^{−100}\)。
因此如果想要在一组询问中有高概率获得正确答案,那么需要 \(O(\log V)\) 个序列。\(q\) 组询问就是 \(O(\log qV)\) 个。
显然对于这题我们只需要单点修改和区间查询,坐标离散化后树状数组即可。
Code
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mp make_pair
using namespace std;
const int N=5e4+10,K=75;
int n,m,tot; bool a[N][K+3]; pii tmp[N];
struct Q{int opt,x,y;}q[N];
struct BITree{
    #define lobit(x) ((x)&-(x))
    int tree[N];
    void add(int pos,int x){for(int i=pos;i<=tot;i+=lobit(i))tree[i]^=x;}
    int _query(int pos){int res=0;for(int i=pos;i;i-=lobit(i))res^=tree[i];return res;}
    int query(int l,int r){return _query(r)^_query(l-1);}
    #undef lobit
}tr[K+3];
struct base{
    int b[35];
    void clear(){memset(b,0,sizeof b);}
    void insert(int x){for(int i=30;~i;i--)if(x&(1<<i)){if(!b[i]){b[i]=x;return;}x^=b[i];}}
    int query(int x){for(int i=30;~i;i--)if(!(x&(1<<i)))x^=b[i];return x;}
}b;
int main(){
    srand(0x0d000721); cin>>m>>n;
    for(int i=1;i<=m;i++){
        cin>>q[i].opt>>q[i].x>>q[i].y;
        if(q[i].opt==1) tmp[++tot]=mp(q[i].x,q[i].y);
    }
    sort(tmp+1,tmp+tot+1);
    for(int i=1;i<=m;i++){
        if(q[i].opt==1) q[i].x=lower_bound(tmp+1,tmp+tot+1,mp(q[i].x,q[i].y))-tmp;
        else{
            q[i].x=lower_bound(tmp+1,tmp+tot+1,mp(q[i].x,0))-tmp;
            q[i].y=upper_bound(tmp+1,tmp+tot+1,mp(q[i].y,INT_MAX))-tmp-1;
        }
    }
    for(int i=1;i<=tot;i++) for(int j=1;j<=K;j++) a[i][j]=rand()&1;
    for(int i=1;i<=m;i++){
        if(q[i].opt==1) for(int j=1;j<=K;j++) if(a[q[i].x][j]) tr[j].add(q[i].x,q[i].y);
        else{b.clear(); for(int j=1;j<=K;j++) b.insert(tr[j].query(q[i].x,q[i].y)); cout<<b.query(0)<<'\n';}
    }
    return 0;
}
让我们一起赞美伟大的 zky 吧!\zky/\zky/\zky/

                
            
        
浙公网安备 33010602011771号