RMQ(或运算)
RMQ
https://ac.nowcoder.com/acm/contest/283/J
题目描述
按位或运算:处理两个长度相同的二进制数,两个相应的二进位中只要有一个为1,该位的结果值为1。例如5 or 3 = 7
0101(十进制5) OR 0011(十进制3) = 0111(十进制7)—— 引用自 位运算——维基百科
小姐姐想要一种数据结构,支持如下操作:
对于一个整数数组:
1. 给定L和R,输出[L,R]中元素的和
2. 给定L,R和X,将[L,R]中每个元素与X进行按位或运算
3. 数组索引从1开始
按位或在C\C++、Java、Python中为'|'运算符
输入描述:
第一行为两个整数 n 和 m,表示数组元素个数和操作的次数
第二行有n个整数,第i个表示数组array中第i个元素的值array[i]
接下来m行,每行只有两种可能:
1. SUM L R
表示对[L,R]的元素求和并输出
2. OR L R X
表示对[L,R]的每一个元素与X进行按位或运算,L、R为base 1的数字序号
数据满足:
输出描述:
对于每个SUM操作,在一行内输出该操作的结果。
示例1
输入
5 3 1 2 3 4 5 SUM 1 4 OR 2 5 10 SUM 1 4
输出
10 36
说明
在第一个SUM操作时数组a为[1, 2, 3, 4, 5],因此[1,4]和为10
在第二个SUM操作时数组a为[1, 10, 11, 14, 15],因此[1,4]和为36
1 #include<bits/stdc++.h> 2 #define maxn 200005 3 #define lson l,mid,rt<<1 4 #define rson mid+1,r,rt<<1|1 5 typedef long long ll; 6 using namespace std; 7 ll tree[maxn<<3],lazy[maxn<<3]; 8 9 int n,m; 10 11 void push_up(int rt){ 12 tree[rt]=tree[rt<<1]+tree[rt<<1|1]; 13 lazy[rt]=lazy[rt<<1]|lazy[rt<<1|1]; 14 } 15 16 17 void build(int l,int r,int rt){ 18 if(l==r){ 19 cin>>tree[rt]; 20 lazy[rt]=~tree[rt]; 21 return; 22 } 23 int mid=(l+r)/2; 24 build(lson); 25 build(rson); 26 push_up(rt); 27 } 28 29 ll query(int L,int R,int l,int r,int rt){ 30 if(L<=l&&R>=r){ 31 return tree[rt]; 32 } 33 ll ans=0; 34 int mid=(l+r)/2; 35 if(L<=mid) ans+=query(L,R,lson); 36 if(R>mid) ans+=query(L,R,rson); 37 push_up(rt); 38 return ans; 39 } 40 41 void add(int L,int R,int v,int l,int r,int rt){ 42 if(l==r){ 43 tree[rt]+=lazy[rt]&v; 44 lazy[rt]-=lazy[rt]&v; 45 return; 46 } 47 int mid=(l+r)/2; 48 if(!(lazy[rt]&v)) return; 49 if(L<=mid) add(L,R,v,lson); 50 if(R>mid) add(L,R,v,rson); 51 push_up(rt); 52 53 } 54 55 int main(){ 56 std::ios::sync_with_stdio(false); 57 cin>>n>>m; 58 build(1,n,1); 59 string str; 60 int x,y,v; 61 while(m--){ 62 cin>>str>>x>>y; 63 if(x>y) swap(x,y); 64 if(str=="SUM"){ 65 cout<<query(x,y,1,n,1)<<endl; 66 } 67 else{ 68 cin>>v; 69 add(x,y,v,1,n,1); 70 } 71 } 72 73 }
posted on 2018-11-27 13:17 Fighting_sh 阅读(341) 评论(0) 编辑 收藏 举报