西安邀请赛2021J Reverse(Trie)
题意
有两种操作
操作0:大于k的数字x,然后找到x与k第一次不相等的位数然后反转后面
操作1 查询[l,r]的个数
输入
1
6 3
1 2 3 4 5 5
1 3 6
0 3
1 3 6
输出
4
3
思路
翻转操作用tg标记一下,懒标记,每次统计跑一遍trie树
代码
/*made in mrd*/
#include
using namespace std;
const int N=2e5+10;
#define int long long
#define mem(a,b) memset(a,b,sizeof a)
#define fi first
#define se second
#define pii pair
int tr[200010*32][2],nn,siz[200010*32];
int dex;
bool tg[200010*32];
void ad(int x)
{
int curr=0;
for(int i=31;i>=0;i--)
{
int g=(x>>i)&1;
if(tr[curr][g]==0){
tr[curr][g]=++dex;
tr[dex][0]=tr[dex][1]=siz[dex]=0;
tg[dex]=0;
}
++siz[curr];
curr=tr[curr][g];
}
++siz[curr];
}
void pd(int x)
{
if(!tg[x]) return ;
swap(tr[x][0],tr[x][1]);
tg[x]=0;
if(tr[x][0]) tg[tr[x][0]]^=1;
if(tr[x][1]) tg[tr[x][1]]^=1;
}
void mdf(int x,int dep,int k)
{
if(dep==-1||(x==0&dep!=31)) return ;
pd(x);
int g=(k>>dep)&1;
if(g) {
mdf(tr[x][1],dep-1,k);
return ;
}
if(tr[x][1]) tg[tr[x][1]]^=1;
mdf(tr[x][0],dep-1,k);
}
int calc(int x,int dep,int k)
{
if(dep==-1||x==0&&dep!=31) return (x==0)?0:siz[x];
pd(x);
int g=(k>>dep)&1;
if(g) return (tr[x][0]==0?0:siz[tr[x][0]])+calc(tr[x][1],dep-1,k);
return calc(tr[x][0],dep-1,k);
}
void print(int x,int dep,int curr)
{
if(dep==-1)
{
for(int i=0;i>t;
while(t--)
{
cin>>n>>m;
tr[0][0]=tr[0][1]=siz[0]=0;
tg[0]=0;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
ad(x);
}
print(0,31,0);
int opt,x,y;
while(m--)
{
cin>>opt>>x;
if(opt==1) {
cin>>y;
cout<