二进制拆分线段树
时间:2019-10-08
本文章向大家介绍二进制拆分线段树,主要包括二进制拆分线段树使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
noip 模拟20190907 T3 位运算(bit)
/*
reference:
translation:
solution:
trigger:
note:
*
record:
date:
2019.09.04
*/
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dwn(i,a,b) for(int i=a;i>=b;--i)
template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;}
inline void write(int n){if(n==0)return;write(n/10);putchar(n%10+'0');}
#define mem(a,b) memset(a,b,sizeof(a))
#define ee(i,u) for(int i=head[u];i;i=e[i].next)
#define lson (o<<1)
#define rson (o<<1|1)
const int N=2e5+10,M=1e5+50,inf=0x3f3f3f3f;
int n,m,a[N],K[25];
struct tree{
int l,r;
int tg[25];bool val[25];
}t[N<<2];
inline void pushup(int o){
rep(i,0,20)
t[o].val[i]=t[lson].val[i]^t[rson].val[i];
}
inline void pushdown(int o,int l,int r){
int mid=l+r>>1;
rep(i,0,20){
if(t[o].tg[i]==0)continue;
if(t[o].tg[i]==1)
t[lson].val[i]=t[rson].val[i]=0;
else if(t[o].tg[i]==2)
t[lson].val[i]=(mid-l+1)&1,t[rson].val[i]=(r-mid)&1;//区间赋为1 异或和:奇为1 偶为0
t[lson].tg[i]=t[rson].tg[i]=t[o].tg[i];
t[o].tg[i]=0;
}
}
void And(int o,int l,int r,int x,int y){
if(l>y||r<x) return;
if(x<=l&&r<=y){
rep(i,0,20)
if(!K[i])
t[o].val[i]=0,t[o].tg[i]=1;
return;
}
pushdown(o,l,r);
int mid=l+r>>1;
And(lson,l,mid,x,y),And(rson,mid+1,r,x,y);
pushup(o);
}
void Or(int o,int l,int r,int x,int y){
if(l>y||r<x) return;
if(x<=l&&r<=y){
rep(i,0,20)
if(K[i])
t[o].val[i]=(r-l+1)&1,t[o].tg[i]=2;
return;
}
pushdown(o,l,r);
int mid=l+r>>1;
Or(lson,l,mid,x,y),Or(rson,mid+1,r,x,y);
pushup(o);
}
int Ans,ans[20];
void Xor(int o,int l,int r,int x,int y){
if(l>y||r<x) return;
if(x<=l&&r<=y){
rep(i,0,20)
ans[i]^=t[o].val[i];
return;
}
pushdown(o,l,r);
int mid=l+r>>1;
Xor(lson,l,mid,x,y);
Xor(rson,mid+1,r,x,y);
pushup(o);
}
void print(int l,int r){
Ans=0;
mem(ans,0);
Xor(1,1,n,l,r);
rep(i,0,20)
if(ans[i])
Ans|=(1<<i);
printf("%d\n",Ans);
}
inline void build(int o,int l,int r){
t[o].l=l,t[o].r=r;
if(l==r){
rep(i,0,20)t[o].val[i]=(a[l]>>i)&1;
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(o);
}
int main(){
#ifdef WIN32
freopen("t3.txt","r",stdin);
//freopen("and.out","w",stdout);
#endif
rd(n),rd(m);
rep(i,1,n)rd(a[i]);
build(1,1,n);
while(m--){
int op,x,y,k;
rd(op);
if(op==3) rd(x),rd(y),print(x,y);
else{
rd(x),rd(y),rd(k);
rep(i,0,20)K[i]=(k>>i)&1;
if(op==1) And(1,1,n,x,y);
else if(op==2) Or(1,1,n,x,y);
}
}
printf("%.3lf M",(double)sizeof(t)/(1<<20));
return 0;
}
线段树+二进制位拆分【CF242E】XOR on Segment
/*
reference:
translation:
solution:
由于异或不具有叠加性,所以不能用lazylazy标记直接异或。
我们记录t[o].val[i]代表当前节点o,二进制位i上是1的数有多少个。
由于,如果某一二进制位上原来为1,且当前异或的数x的二进制位上也有1,
那么我们的当前t[o].val[i]=r-l+1-t[o].val[i]
可以理解为01交换。
然后由于2^20比10^6要大。所以只需要拆到20即可。
然后直接计算即可。
trigger:
note:
*
record:
date:
2019.09.07
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dwn(i,a,b) for(int i=a;i>=b;--i)
template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;}
inline void write(int n){if(n==0)return;write(n/10);putchar(n%10+'0');}
#define mem(a,b) memset(a,b,sizeof(a))
#define ee(i,u) for(int i=head[u];i;i=e[i].next)
#define lson (o<<1)
#define rson (o<<1|1)
const int N=1e5+10;
int n,m;
struct tree{
int l,r;
int tag,val[21];
}t[N<<2];
inline void pushup(int o){
dwn(i,20,0)
t[o].val[i]=t[lson].val[i]+t[rson].val[i];
}
inline void build(int o,int l,int r){
t[o].l=l,t[o].r=r;
if(l==r){
int x;rd(x);
dwn(i,20,0)
if((x>>i)&1)
t[o].val[i]=1;
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(o);
}
inline void pushdown(int o){
if(t[o].tag==0)return ;
int l=t[o].l,r=t[o].r;
int mid=l+r>>1;
dwn(i,20,0){
if((t[o].tag>>i)&1){
t[lson].val[i]=mid-l+1-t[lson].val[i];
t[rson].val[i]=r-mid-t[rson].val[i];
}
}
t[lson].tag^=t[o].tag;//继承
t[rson].tag^=t[o].tag;
t[o].tag=0;//清零
}
inline void change(int o,int x,int y,int k){
int l=t[o].l,r=t[o].r;
if(x<=l && r<=y){
t[o].tag^=k;
dwn(i,20,0)
if((k>>i)&1)
t[o].val[i]=r-l+1-t[o].val[i];
return ;
}
pushdown(o);
int mid=l+r>>1;
if(x<=mid)change(lson,x,y,k);
if(mid<y)change(rson,x,y,k);
pushup(o);
}
inline int query(int o,int x,int y){
int l=t[o].l,r=t[o].r;
if(x<=l && r<=y){
int res=0;
dwn(i,20,0)
res+=(1<<i)*t[o].val[i];
return res;
}
pushdown(o);
int mid=l+r>>1;
int ans=0;
if(x<=mid)ans+=query(lson,x,y);
if(mid<y)ans+=query(rson,x,y);
return ans;
}
signed main(){
#ifdef WIN32
freopen("CF242E.txt","r",stdin);
#endif
rd(n);
build(1,1,n);
rd(m);
while(m--){
int op,l,r,x;
rd(op);
if(op==1){
rd(l),rd(r);
printf("%lld\n",query(1,l,r));
}
else{
rd(l),rd(r),rd(x);
change(1,l,r,x);
}
}
// printf("%.3lf M",(double)sizeof(t)/(1<<20));
return 0;
}
/*
5
4 10 3 13 7
8
1 2 4
2 1 3 3
1 2 4
1 3 3
2 2 5 5
1 1 5
2 1 2 10
1 2 3
*/
/*
26
22
0
34
11
*/
/*
6
4 7 4 0 7 3
5
2 2 3 8
1 1 5
2 3 5 1
2 4 5 6
1 2 3
*/
/*
38
28
*/
/*
Description
给定一个长为n(n<=10^5)n(n<=10^5)的数组
数组里的数不超过10^6
有两种操作:
1:求sum[l,r];
2:对[l,r]中的所有数^x
Input
第一行一个整数nn,代表有一个长度为nn的数组。
第二行nn个整数,代表aiai
第三行为一个整数mm,代表有mm次操作。
接下来mm行每行描述一个操作。
Output
对于每一个操作11,输出一行代表sum[l,r]sum[l,r].
*/
原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11634687.html
- 使用Oracle中的emp,dept来学习Django ORM
- 内部类
- 初学java之接口基础
- java之内部类
- html学习第一讲(内容html常规控件的的使用)
- uva----(10794) A Different Task
- uva-----(11384)Help is needed for Dexter
- uva------(11464)Even Parity
- java SE学习之线程同步(详细介绍)
- java多线程的常用方法(以及注意事项)
- MFC学习之窗口基础
- java多线程下如何调用一个共同的内存单元(调用同一个对象)
- java之多线程(Thread)
- HDUOJ------3336 Count the string(kmp)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于python实现计算两组数据P值
- PHP getNamespaces()函数讲解
- OpenCV 使用imread()函数读取图片的六种正确姿势
- PHP simplexml_import_dom()函数讲解
- PHP getName()函数讲解
- Laravel框架集成UEditor编辑器的方法图文与实例详解
- PHP+redis实现的购物车单例类示例
- ThinkPHP3.2.3框架邮件发送功能图文实例详解
- PHP simplexml_load_file()函数讲解
- Python下划线5种含义代码实例解析
- PHP getDocNamespaces()函数讲解
- Django实现内容缓存实例方法
- Tensorflow–取tensorf指定列的操作方式
- spring-boot-route(一)Controller接收参数的几种方式
- python中 _、__、__xx__()区别及使用场景