由于太弱所以模板还不全,比如xor最大路径之类的问题,位运算和字符串问题还是有些欠缺,抽空把SA和BKDRhash学一下吧qwq。
速度上01字典树比线性基快。
01字典树
数组中找一个数异或一个数k后
最大,最小。
询问一个数存不存在。(这个就算了,没用)
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int nxt[N*30][2], cnt;
int val[N];
int a[N];
void init()
{
nxt[0][0]=0;
nxt[0][1]=0;
cnt=1;
}
void add(int n)
{
int p=0;
for (int i=20;i>=0;--i)
{
int bit=(n>>i)&1;
if(!nxt[p][bit])
{
nxt[cnt][0]=nxt[cnt][1] = 0;
nxt[p][bit]=cnt++;
}
p = nxt[p][bit];
}
val[p] = n;
}
int q_max(int x)
{
int p=0;
for(int i=20;i>=0;i--)
{
int bit=((x>>i)&1);
if(nxt[p][bit^1])
{
p=nxt[p][bit^1];
}
else
{
p=nxt[p][bit];
}
}
return val[p]^x;
}
int q_min(int x)
{
int p=0;
for(int i=20;i>=0;i--)
{
int bit=((x>>i)&1);
if(nxt[p][bit])
{
p=nxt[p][bit];
}
else
{
p=nxt[p][bit^1];
}
}
return val[p]^x;
}
int main()
{
int t;
for(cin>>t;t;t--)
{
init();
int l,r;
cin>>l>>r;
for(int i=l;i<=r;i++)
{
cin>>a[i];
add(a[i]);
}
for(int i=l;i<=r;i++)
{
int x=a[i]^l;
if(q_max(x)==r&&q_min(x)==l)
{
cout<<x<<endl;
break;
}
}
}
return 0;
}
线性基
对于n个数的数组,我们希望用一个代表数组来表示,这个代表数组能通过一系列的异或操作得到原数组,这个代表数组称为线性基。
线性基构造思路:
对于原数组中每一个数都去尝试插入线性基中,对于待插入x的所有二进制位,如果x的这一二进制位是1并且线性基为空,那么这一位置线性基就是x,否则让x异或上这一位置线性基。
求最大值思路:
我们从高位到低位开始贪心,如果这一位线性基存在并且答案ans的这一二进制位为0,那么让ans异或上这一位线性基
求最小是思路:
如果有数插入失败,证明出现重复数字直接特判为0
否则,由低到高第一位不为0的线性基就是最小值
求第k小思路:
用n个数异或询问
最大,最小,存不存在,第k小
#include <iostream>
using namespace std;
const int maxbit=51;
#define ll long long
const int N = 1e5+100;
ll a[N],d[63],k;
int n;
bool falg;
void getxxj()
{
for(int i=1;i<=n;i++)
{
long long temp=a[i];
for(int j=maxbit;j>=0;j--)
{
if(temp&(1ll<<j))
{
if(d[j]==0)
{
d[j]=temp;
break;
}
else
{
falg=true;
temp^=d[j];
}
}
}
}
}
ll q_min()
{
if(falg)
return 0;
ll ans;
for(int i=0;i<=maxbit;i++)
{
if(d[i])
{
ans=d[i];
}
}
return ans;
}
ll q_max()
{
long long ans=0;
for(int i=maxbit;i>=0;i--)
{
if((ans&(1ll<<i))==0&&d[i])
{
ans^=d[i];
}
}
return ans;
}
ll q_k(ll k)
{
int i=0;
ll ans=0ll;
while(k)
{
if(k&1)
{
ans^=d[i];
}
i++;
k>>=1;
}
return ans;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
getxxj();
cout<<q_max()<<endl;
cout<<q_min()<<endl;
cin>>k;
if(falg)
k--;
cout<<q_k(k)<<endl;
return 0;
}