链接:https://ac.nowcoder.com/acm/contest/283/J
来源:牛客网
对于一个整数数组:
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
解题思路
读题,线段树裸题,然而由于题量太少,一开始没有想到 或运算 的传递性,赛后看了眼题解,明白是位运算的传递性,注意这里维护的懒惰标记是上一次没有做 或运算的数,所以当需要修改懒惰标记的时候,不应该直接+=,由于这里的关系传递是或运算,所以这里要写成|=,来自菜鸡的补题思路。
Code
#include <iostream> #define ll long long #define lson left,mid,k<<1 #define rson mid+1,right,k<<1|1 #define imid int mid=(left+right)>>1 using namespace std; struct node { int l; int r; ll sum[25]; ll mark;//待 或运算的数 }que[200005 * 4]; int ql, qr; ll val, a[200005]; void up(int k) { for (int i = 0; i < 25; i++) { que[k].sum[i] = que[k << 1].sum[i] + que[k << 1 | 1].sum[i]; } } void down(int k) { if (que[k].mark) { que[k << 1].mark |= que[k].mark; que[k << 1 | 1].mark |= que[k].mark; for (int i = 0; i < 25; i++) { if (que[k].mark & (1 << i)) { que[k << 1].sum[i] = (que[k << 1].r - que[k << 1].l + 1); que[k << 1 | 1].sum[i] = (que[k << 1 | 1].r - que[k << 1 | 1].l + 1); } } que[k].mark = 0; } } void build(int left, int right, int k) { que[k].l = left; que[k].r = right; que[k].mark = 0; if (left == right) { for (int i = 0; i < 25; i++) { if (a[left] & (1 << i)) que[k].sum[i] = 1; else que[k].sum[i] = 0; } return; } imid; build(lson); build(rson); up(k); } void update(int left, int right, int k) { if (qr < left || right < ql) return; if (ql <= left && right <= qr) { for (int i = 0; i < 25; i++) if ((1 << i)&val) que[k].sum[i] = que[k].r - que[k].l + 1; que[k].mark |= val; return; } imid; down(k); update(lson); update(rson); up(k); } ll query(int left, int right, int k) { if (qr < left || right < ql) return 0; if (ql <= left && right <= qr) { ll ans = 0; for (int i = 0; i < 25; i++) ans += que[k].sum[i] * (1 << i); return ans; } imid; down(k); return query(lson) + query(rson); } int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); build(1, n, 1); char op[10]; while (m--) { scanf("%s", op); if (op[0] == 'S') { scanf("%d%d", &ql, &qr); printf("%lld\n", query(1, n, 1)); } else { scanf("%d%d%lld", &ql, &qr, &val); update(1, n, 1); } } }