传送门: https://ac.nowcoder.com/acm/contest/16/C
题意
给
你
n
个
数
A
1
.
.
.
A
n
,
m
个
操
作
。
给你n个数A_1...A_n,m个操作。
给你n个数A1...An,m个操作。
操
作
分
两
种
:
操作分两种:
操作分两种:
- 操 作 一 : 1 x y , 将 A x 改 成 y 操作一:1\;x\;y,将A_x改成y 操作一:1xy,将Ax改成y
- 操 作 二 : 2 l r , 求 [ A l . . . A r ] 所 有 子 集 的 & 并 m o d 1 e 9 + 7 操作二:2\;l\;r,求[A_l...A_r]所有子集的\&并mod\;1e9+7 操作二:2lr,求[Al...Ar]所有子集的&并mod1e9+7
思路
这
题
一
看
就
知
道
树
状
数
组
或
者
线
段
树
去
做
。
这题一看就知道树状数组或者线段树去做。
这题一看就知道树状数组或者线段树去做。
因
为
和
位
运
算
有
关
,
所
以
考
虑
每
个
数
的
二
进
制
位
。
因为和位运算有关,所以考虑每个数的二进制位。
因为和位运算有关,所以考虑每个数的二进制位。
比 如 ( 3 ) 2 = 11 , 则 贡 献 为 2 0 ∗ ( 2 1 − 1 ) + 2 1 ∗ ( 2 1 − 1 ) 比如(3)_2=11,则贡献为2^0*(2^1-1)+2^1*(2^1-1) 比如(3)2=11,则贡献为20∗(21−1)+21∗(21−1)
因 为 是 & 操 作 , 所 以 该 位 上 必 须 都 是 1 才 行 , 所 以 统 计 该 位 上 有 多 少 1 即 可 。 因为是\&操作,所以该位上必须都是1才行,所以统计该位上有多少1即可。 因为是&操作,所以该位上必须都是1才行,所以统计该位上有多少1即可。
比 如 1 , 2 , 3 为 1 , 10 , 11 , 则 组 合 起 来 为 22 , 贡 献 为 2 0 ∗ ( 2 2 − 1 ) + 2 1 ∗ ( 2 2 − 1 ) 比如1,2,3为1,10,11,则组合起来为22,贡献为2^0*(2^2-1)+2^1*(2^2-1) 比如1,2,3为1,10,11,则组合起来为22,贡献为20∗(22−1)+21∗(22−1)
如 何 更 新 和 查 询 ? 线 段 树 ! 如何更新和查询?线段树! 如何更新和查询?线段树!
只 不 过 更 新 的 是 一 个 数 的 二 进 制 数 组 而 已 。 只不过更新的是一个数的二进制数组而已。 只不过更新的是一个数的二进制数组而已。
Code
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 4e5 + 10;
#define lc u << 1
#define rc u << 1 | 1
#define mid (t[u].l + t[u].r) / 2
struct Tree {
int l, r;
ll OR[55];
}t[N << 2];
ll bit[N], a[N];
inline void push_up(int u) {
for(int i = 0;i <= 32; i++) {
t[u].OR[i] = (t[lc].OR[i] + t[rc].OR[i]) % mod;
}
}
void build(int u, int l, int r) {
t[u].l = l; t[u].r = r;
if(l == r) {
for(int i = 0;i <= 32; i++) {
t[u].OR[i] += a[l] & 1;
a[l] >>= 1;
}
return ;
}
int m = (l + r) >> 1;
build(lc, l, m);
build(rc, m + 1, r);
push_up(u);
}
void modify(int u, int p, ll v) {
if(t[u].l == t[u].r) {
for(int i = 0;i <= 32; i++) {
t[u].OR[i] = v & 1;
v >>= 1;
}
return ;
}
if(p <= mid) modify(lc, p, v);
else modify(rc, p, v);
push_up(u);
}
vector<ll> query(int u, int ql, int qr) {
if(ql <= t[u].l && t[u].r <= qr) {
vector<ll> ans(33, 0);
for(int i = 0;i <= 32; i++) ans[i] = t[u].OR[i];
return ans;
}
vector<ll> ans(33, 0), temp1(33, 0), temp2(33, 0);
if(ql <= mid) temp1 = query(lc, ql, qr);
if(qr > mid) temp2 = query(rc, ql, qr);
for(int i = 0;i <= 32; i++) ans[i] = temp1[i] + temp2[i];
return ans;
}
void solve() {
bit[0] = 1;
for(int i = 1;i < N; i++) bit[i] = bit[i - 1] * 2 % mod;
int n; scanf("%d",&n);
for(int i = 1;i <= n; i++) scanf("%lld",&a[i]);
build(1, 1, n);
int m; scanf("%d",&m);
while(m--) {
int opt; scanf("%d",&opt);
if(opt == 1) {
int x; ll y; scanf("%d%lld",&x,&y);
modify(1, x, y);
}
else {
int l, r; scanf("%d%d",&l,&r);
vector<ll> ans = query(1, l, r);
ll res = 0;
for(int i = 0;i <= 32; i++) {
res = (res + bit[i] % mod * (bit[ans[i]] - 1 + mod) % mod) % mod;
}
printf("%lld\n",res);
}
}
}
signed main() {
solve();
}