https://codeforces.com/contest/587/problem/E

一个序列,

1区间异或操作

2查询区间子集异或种类数

题解

解题思路大同小异,都是利用异或的性质进行转化,std和很多网友用的都是差分的思想,用两棵线段树

第一棵维护差分序列上的线性基,第二棵维护原序列的异或区间和,两者同时进行修改

考虑两个序列 $(a,b)(d,e)$,按照std的想法,应该是维护$(0 \^ a,a \^ b)(0 \^ d,d \^ e)$ 然后合并首尾变成$(0 \^ a,a \^ b,b \^ d,d \^ e)$

但由于异或的性质,我们直接每个区间保存下区间左端点原来的信息,

直接先插入两个序列的线性基,然后新头部的异或和即可,也就是$(0 \^a,a \^b,a \^ d,d \^e)$

写起来更加轻松

#include <bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define fi first
#define se second
#define mp make_pair
#define pii pair<ll,ll>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(register int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(register int ii=b;ii>=a;--ii)
#define forn(ii,x) for(int ii=head[x];ii;ii=e[ii].next)
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show5(v,w,x,y,z) cout<<#v<<" "<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define showa(a,b) cout<<#a<<'['<<b<<"]="<<a[b]<<endl
using namespace std;
const int maxn=2e5+10,maxm=2e5+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
//heads
int casn,n,m,k;
class segtree{public:
#define nd node[now]
#define ndl node[now<<1]
#define ndr node[now<<1|1]
struct segnode{
int l,r,flag,val;
int d[32];
inline void init(){val=flag=0;memset(d,0,sizeof d);}
inline void insert(ll x){
for(register int i=30;x&&i>=0;--i)
if(x&(1ll<<i)){
if(!d[i]) {d[i]=x;return;}
else x^=d[i];
}
}
int count(){int ans=0;per(i,0,30) if(d[i])ans++; return ans;}
void update(int x){val^=x;flag^=x;}
}node[maxn<<2|3];
inline segnode marge(segnode &a,segnode b)const {
segnode ans;ans.init();
per(i,0,30) ans.insert(a.d[i]),ans.insert(b.d[i]);
ans.insert(a.val^b.val);
ans.val=a.val;
ans.l=a.l,ans.r=b.r;
return ans;
}
inline void down(int now){
if(nd.flag){
ndl.update(nd.flag);ndr.update(nd.flag);
nd.flag=0;
}
}
void maketree(int s,int t,int now=1){
nd.l=s,nd.r=t;nd.init();
if(s==t) {cin>>nd.val;return ;}
maketree(s,(s+t)/2,now<<1);
maketree((s+t)/2+1,t,now<<1|1);
nd=marge(ndl,ndr);
}
void update(int s,int t,int x,int now=1){
if(s<=nd.l&&t>=nd.r) {nd.update(x);return;}
down(now);
if(s<=ndl.r) update(s,t,x,now<<1);
if(t>ndl.r) update(s,t,x,now<<1|1);
nd=marge(ndl,ndr);
}
segnode query(int s,int t,int now=1){
if(s<=nd.l&&t>=nd.r) {
if(s==nd.l) {
segnode x;x.init();
return marge(x,nd);
}else return nd;
}
down(now);
segnode ans;ans.init();
if(s<=ndl.r) ans=marge(ans,query(s,t,now<<1));
if(t>ndl.r) ans=marge(ans,query(s,t,now<<1|1));
nd=marge(ndl,ndr);
return ans;
}
}tree;
int main() {
IO;
cin>>n>>m;
register int a,b,c,d;
tree.maketree(1,n);
while(m--){
cin>>a>>b>>c;
if(a==1){
cin>>d;tree.update(b,c,d);
}else cout<<(1<<tree.query(b,c).count())<<endl;
}
}

最新文章

  1. requestAnimationFrame,Web中写动画的另一种选择
  2. TWRP基于omnirom 6.0.1编译教程
  3. crontab每秒执行URL接口
  4. POJ3469 Dual Core CPU(最小割)
  5. javascript 全局变量 局部变量 var 与不加var的区别
  6. javascript加载顺序
  7. 内网渗透中的反弹Shell与端口转发
  8. php命名空间学习
  9. Redis批量导入数据
  10. Android之获取联系人
  11. XSS 简单理解之:AntiSamy
  12. web系统架构的演进变化很形象
  13. 什么是WEBserver? 经常使用的WEBserver有哪些?
  14. mitx一大堆统计学知识
  15. Redis纠错
  16. [BZOJ3038]遥远的国度
  17. 用 Anaconda 完美解决 Python2 和 python3 共存问题
  18. 客服端与服务端APP支付宝支付接口联调的那些坑
  19. 使用gitolite进行git服务器搭建
  20. 解决只有单引号的Json格式转换成bean问题

热门文章

  1. VS + QT 出现 LNK2001 无法解析的外部符号 QMetaObject 的问题
  2. 工具(2): 极简MarkDown排版介绍(How to)
  3. Java队列学习
  4. java学习——JDK1.8接口和实现类
  5. jsonp 实现前端跨域
  6. Vue.js 2.x笔记:状态管理Vuex(7)
  7. Kafka概述(一)
  8. pixy&amp;STM32使用记录(串口&amp;SPI外设)
  9. magento-2.2.6-1VM环境镜像-沙箱 - - 完全隔离的环境
  10. Day062--django--模板,母版和继承