暂无链接
异或
【题目描述】
蒜头是一位优秀的 OI 选手。
自古以来,迷人的星空总是吸引着许多天文学的爱好者。顺着星星的指引,明天的蒜头将会遇到一道 有趣的题,和蒜头曾经出过的一道题一样有趣。
给一个长度为nn的序列,qq次询问在中选择若干个数(可以不选)和dd异或所能得到的最大值。
【输入】
输入的第一行是一个数,表示序列的长度。
接下来一行nn个数,第个数表示序列的第ii个元素。
接下来一行是一个数,表示询问数。
接下来qq行,每行三个数表示一组询问。
【输出】
共输出qq行,第行表示第ii个询问的答案。
【输入样例】
17
564336209 776981317 868432406 79690390 105769824 521627888 858214260 66699280 76283981 338813935 566669033 929900644 508668884 239924833 9927169 356446378 777851615
20
8 8 326049892
1 8 950790720
10 12 76241722
7 7 324181335
5 9 89862960
3 6 313463619
4 9 897057197
1 6 840260745
1 3 1068836159
3 7 33253290
4 6 628314026
7 12 1010898432
4 9 49135963
10 17 359110673
4 9 403969940
2 9 369688276
3 7 709921095
2 6 618680372
5 7 238186905
10 10 886901243
【输出样例】
326049892
1072550086
870740830
544592419
927225721
1048265125
934931072
1063393342
1068836159
914859818
1054596556
1069078032
934584212
1070493062
938347227
1072003701
934670401
1061732946
1024802541
886901243
【提示】
每个子任务七个测试点,依次分布。
题解
出题人题解:
时间复杂度瓶颈在于我们要表示出O(loga)O(loga)个线性基。
考虑我们之前维护端点的过程,那么后ii个端点实际上就是一个
大小为的线性无关组。
容易发现,我们将位置在前面的数异或位置在后面的数,并不会
对我们的答案产生影响。所以实际上我们仍然可以维护线性基,
并且只需维护11个。
实现上来说,只要同时存在两个最高位相同的数时,用前面的异
或后面的即可。
时间复杂度。
代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e6+5;
struct sd{int ri,d,id;};
vector<sd>que[M];
int ans[M],a[M],n,q,pos[40],base[40];
void in()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
scanf("%d",&q);
}
void ac()
{
int le,ri,d;
for(int i=1;i<=q;++i)
{
scanf("%d%d%d",&le,&ri,&d);
que[le].push_back((sd){ri,d,i});
}
memset(pos,63,sizeof(pos));
int v,p,re;
for(int i=n;i>=1;--i)
{
v=a[i],p=i;
for(int j=30;j>=0;--j)
{
if(v>>j&1)
{
v^=base[j];
if(pos[j]>p)
base[j]^=v,swap(pos[j],p);
}
if(!v)break;
}
for(int j=que[i].size()-1;j>=0;--j)
{
d=que[i][j].d;ri=que[i][j].ri;
for(int k=30;k>=0;--k)if(pos[k]<=ri&&~d>>k&1)d^=base[k];
ans[que[i][j].id]=d;
}
}
for(int i=1;i<=q;++i)
printf("%d\n",ans[i]);
}
int main()
{
in();ac();
return 0;
}