题解 P5670【秘籍-反复异或】
这是一篇指令集题解,并非正解。另外,请不要尝试在正式 OI 比赛中使用指令集。
题意
区间加区间后 $m$ 位异或和,$m$ 所有询问相同。
$n,m\le 10^5,0\le a_i< 2^m\le1024$
思路
加/异或,指令集基本操作,这个不用多讲。
虽然已经有了一篇指令集题解,但是我还是来推广一种指令集写法,这种写法的优势在于:
- 好写好记
- 可本地运行
- 运行速度较快(至少在只用
-O2时比现有的一篇指令集题解-O2 -Ofast快1.3s)
这种指令集用 __attribute((vector_size(32))) 实现,可以直接进行一些基本操作,不需要写函数,具体可以直接参考代码。
贴个代码:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned u256 __attribute((vector_size(32)));
#define ll long long
const int N=100000>>3;
int n,m,q;
u256 a[N],ans,tmp;
inline void add(int l,int r,int x){
u256 xx=u256{x,x,x,x,x,x,x,x};
if((l>>3)==(r>>3)){
for(int i=l&7;i<=(r&7);i++){
a[l>>3][i]+=x;
}
}else{
for(int i=l&7;i<=7;i++){
a[l>>3][i]+=x;
}
for(int i=0;i<=(r&7);i++){
a[r>>3][i]+=x;
}
for(int i=(l>>3)+1;i<=(r>>3)-1;i++){
a[i]+=xx;
}
}
}
inline int query(int l,int r){
u256 ans=u256{0,0,0,0,0,0,0,0};
int res=0;
if((l>>3)==(r>>3)){
for(int i=l&7;i<=(r&7);i++){
res^=a[l>>3][i];
}
}else{
for(int i=l&7;i<=7;i++){
res^=a[l>>3][i];
}
for(int i=0;i<=(r&7);i++){
res^=a[r>>3][i];
}
for(int i=(l>>3)+1;i<=(r>>3)-1;i++){
ans^=a[i];
}
for(int i=0;i<=7;i++){
res^=ans[i];
}
}
return res;
}
int main(){
n=read(),m=1<<read(),q=read();
for(int i=0;i<n;i++){
a[i>>3][i&7]=read();
}
while(q--){
int opt=read(),l=read()-1,r=read()-1;
if(opt==1){
add(l,r,read());
}else{
write(query(l,r)%m);
putc('\n');
}
}
flush();
}
谢谢观看,再见 qwq~

浙公网安备 33010602011771号