CodeForces 587 E.Duff as a Queen 线段树动态维护区间线性基
2024-08-26 05:12:35
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;
}
}
最新文章
- requestAnimationFrame,Web中写动画的另一种选择
- TWRP基于omnirom 6.0.1编译教程
- crontab每秒执行URL接口
- POJ3469 Dual Core CPU(最小割)
- javascript 全局变量 局部变量 var 与不加var的区别
- javascript加载顺序
- 内网渗透中的反弹Shell与端口转发
- php命名空间学习
- Redis批量导入数据
- Android之获取联系人
- XSS 简单理解之:AntiSamy
- web系统架构的演进变化很形象
- 什么是WEBserver? 经常使用的WEBserver有哪些?
- mitx一大堆统计学知识
- Redis纠错
- [BZOJ3038]遥远的国度
- 用 Anaconda 完美解决 Python2 和 python3 共存问题
- 客服端与服务端APP支付宝支付接口联调的那些坑
- 使用gitolite进行git服务器搭建
- 解决只有单引号的Json格式转换成bean问题
热门文章
- VS + QT 出现 LNK2001 无法解析的外部符号 QMetaObject 的问题
- 工具(2): 极简MarkDown排版介绍(How to)
- Java队列学习
- java学习——JDK1.8接口和实现类
- jsonp 实现前端跨域
- Vue.js 2.x笔记:状态管理Vuex(7)
- Kafka概述(一)
- pixy&;STM32使用记录(串口&;SPI外设)
- magento-2.2.6-1VM环境镜像-沙箱 - - 完全隔离的环境
- Day062--django--模板,母版和继承