很典的一道题,比赛的时候最后不太想写了,赛后看了一下还是挺简单的
每次的查询可以转化为
这个东西显然是可以用trie树维护的
大概讲一下维护的方法
trie树每个点会记录它的整个子树的数值和
我们从高位向低位枚举
如果这一位上x是0,那么nm和i这一位必须相同
如果这一位上x是1,那么如果nm和i这一位可以相同(异或之后这一位变成0),那么整个子树的值都满足条件,我们将这一部分加到ans里。然后如果存在nm和i这一位可以不同的情况,我们继续往下枚举。
最后如果枚举到i==0,这时说明出现了的情况,这种情况当然也是符合题意的,我们加上这部分贡献。
修改直接从高位到低位枚举每次减去原来的数值加上修改后的数值即可
(据说这个题也可以用线段树嗯造,但是我不太会)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<functional>
#include<unordered_map>
#include<bitset>
#include<set>
using namespace std;
#define int long long
#define inf 0x3f3f3f3f
#define N 16252928
int a[N];
int nn, q;
int ii, x;
int trie[N][2];
int vals[N];
int cnt = 0;
void insert(int nm, int val)
{
int idx = 0;
for (int i = 31; i >= 0; i--)
{
if (nm&(1 << i))
{
if (trie[idx][1])
{
idx = trie[idx][1];
vals[idx] += val;
}
else
{
trie[idx][1] = ++cnt;
idx = trie[idx][1];
vals[idx] += val;
}
}
else
{
if (trie[idx][0])
{
idx = trie[idx][0];
vals[idx] += val;
}
else
{
trie[idx][0] = ++cnt;
idx = trie[idx][0];
vals[idx] += val;
}
}
}
}
void change(int nm, int preval, int val)
{
int idx = 0;
for (int i = 31; i >= 0; i--)
{
idx = trie[idx][bool((1 << i)&nm)];
vals[idx] -= preval;
vals[idx] += val;
}
}
int ex(int X, int ii)
{
int res = 0;
int idx = 0;
for (int i = 31; i >= 0; i--)
{
if ((1 << i)&x)
{
if ((1 << i)&ii)
{
if (trie[idx][1])
{
res += vals[trie[idx][1]];
}
if (!trie[idx][0])break;
idx = trie[idx][0];
}
else
{
if (trie[idx][0])
{
res += vals[trie[idx][0]];
}
if (!trie[idx][1])break;
idx = trie[idx][1];
}
}
else
{
if ((1 << i)&ii)
{
if (!trie[idx][1])break;
idx = trie[idx][1];
}
else
{
if (!trie[idx][0])break;
idx = trie[idx][0];
}
}
if (i == 0)res += vals[idx];
}
return res;
}
signed main(void)
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin >> nn >> q;
for (int i = 0; i < nn; i++)
{
cin >> a[i];
insert(i, a[i]);
}
for (int i = 1; i <= q; i++)
{
int op;
cin >> op;
cin >> ii >> x;
if (op == 1)
{
change(ii, a[ii], x);
a[ii] = x;
}
else
{
int ans = ex(x, ii);
cout << ans << '\n';
}
}
system("pause");
return 0;
}